Completely split the ctf writer part from the main babeltrace2 library.
* Remove the obsolete libbabeltrace2-ctf library
* Add a new libbabeltrace2-ctf-writer library
* Remove the ctf writer includes from the main include file
* Fork an internal copy of assert-pre.h that doesn't use the library
structures.
* Add a logging context specific to ctf writer
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Change-Id: Iff9ab62ee9eeb8abd290fb1d758a73050e21c99b
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1410
Tested-by: jenkins
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
stamp-h1
__pycache__
/babeltrace2.pc
-/babeltrace2-ctf.pc
+/babeltrace2-ctf-writer.pc
TAGS
cscope*
doc/api/Doxyfile
logging \
lib \
python-plugin-provider \
+ ctf-writer \
plugins \
cli \
bindings \
dist_noinst_DATA = CodingStyle
pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = babeltrace2.pc babeltrace2-ctf.pc
+pkgconfig_DATA = babeltrace2.pc babeltrace2-ctf-writer.pc
# This is a convenience target, it's not part of the build process.
CONTRIBUTING.html: CONTRIBUTING.adoc
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Babeltrace CTF parser
+Description: libbabeltrace2-ctf provides the specific bits necessary to write a Common Trace Format (CTF) trace.
+Version: @PACKAGE_VERSION@
+Requires:
+Requires.private: uuid popt
+Libs: -L${libdir} -lbabeltrace2-ctf-writer
+Cflags: -I${includedir}
+
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: Babeltrace CTF parser
-Description: libbabeltrace2-ctf provides the specific bits necessary to read a Common Trace Format (CTF) trace.
-Version: @PACKAGE_VERSION@
-Requires: babeltrace
-Requires.private:
-Libs: -L${libdir} -lbabeltrace2-ctf
-Cflags: -I${includedir}
-
bindings/python/bt2/bt2/__init__.py
common/Makefile
ctfser/Makefile
+ ctf-writer/Makefile
compat/Makefile
cli/Makefile
doc/Makefile
lib/graph/Makefile
lib/graph/message/Makefile
lib/trace-ir/Makefile
- lib/ctf-writer/Makefile
include/Makefile
logging/Makefile
bindings/Makefile
plugins/lttng-utils/Makefile
plugins/lttng-utils/debug-info/Makefile
babeltrace2.pc
- babeltrace2-ctf.pc
+ babeltrace2-ctf-writer.pc
])
AC_CONFIG_FILES([tests/cli/test_intersection], [chmod +x tests/cli/test_intersection])
--- /dev/null
+lib_LTLIBRARIES = libbabeltrace2-ctf-writer.la
+
+libbabeltrace2_ctf_writer_la_SOURCES = \
+ attributes.c \
+ clock.c \
+ clock-class.c \
+ event.c \
+ event-class.c \
+ field-path.c \
+ fields.c \
+ field-types.c \
+ field-wrapper.c \
+ functor.c \
+ logging.c \
+ logging.h \
+ object.c \
+ object-pool.c \
+ resolve.c \
+ stream.c \
+ stream-class.c \
+ trace.c \
+ utils.c \
+ validation.c \
+ values.c \
+ visitor.c \
+ writer.c
+
+libbabeltrace2_ctf_writer_la_LDFLAGS = $(LT_NO_UNDEFINED) \
+ -version-info $(BABELTRACE_LIBRARY_VERSION)
+
+libbabeltrace2_ctf_writer_la_LIBADD = \
+ $(top_builddir)/logging/libbabeltrace2-logging.la \
+ $(top_builddir)/common/libbabeltrace2-common.la \
+ $(top_builddir)/ctfser/libbabeltrace2-ctfser.la \
+ $(top_builddir)/compat/libcompat.la \
+ $(UUID_LIBS)
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/babeltrace-internal.h>
+#include <babeltrace2/compat/string-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/ctf-writer/values-internal.h>
+#include <babeltrace2/ctf-writer/values-internal.h>
+#include <babeltrace2/ctf-writer/values-internal.h>
+#include <inttypes.h>
+
+#define BT_CTF_ATTR_NAME_INDEX 0
+#define BT_CTF_ATTR_VALUE_INDEX 1
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_attributes_create(void)
+{
+ struct bt_ctf_private_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_ctf_private_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_ctf_private_value *attr_obj)
+{
+ BT_LOGD("Destroying attributes object: addr=%p", attr_obj);
+ bt_ctf_object_put_ref(attr_obj);
+}
+
+BT_HIDDEN
+int64_t bt_ctf_attributes_get_count(struct bt_ctf_private_value *attr_obj)
+{
+ return bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj));
+}
+
+BT_HIDDEN
+const char *bt_ctf_attributes_get_field_name(struct bt_ctf_private_value *attr_obj,
+ uint64_t index)
+{
+ const char *ret = NULL;
+ struct bt_ctf_private_value *attr_field_obj = NULL;
+ struct bt_ctf_private_value *attr_field_name_obj = NULL;
+
+ if (!attr_obj) {
+ BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
+ goto end;
+ }
+
+ if (index >= bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj))) {
+ BT_LOGW("Invalid parameter: index is out of bounds: "
+ "index=%" PRIu64 ", count=%" PRId64,
+ index, bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj)));
+ goto end;
+ }
+
+ attr_field_obj = bt_ctf_private_value_array_borrow_element_by_index(
+ 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_ctf_private_value_array_borrow_element_by_index(
+ 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;
+ }
+
+ ret = bt_ctf_value_string_get(
+ bt_ctf_private_value_as_value(attr_field_name_obj));
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_attributes_borrow_field_value(struct bt_ctf_private_value *attr_obj,
+ uint64_t index)
+{
+ struct bt_ctf_private_value *value_obj = NULL;
+ struct bt_ctf_private_value *attr_field_obj = NULL;
+
+ if (!attr_obj) {
+ BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
+ goto end;
+ }
+
+ if (index >= bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj))) {
+ BT_LOGW("Invalid parameter: index is out of bounds: "
+ "index=%" PRIu64 ", count=%" PRId64,
+ index, bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj)));
+ goto end;
+ }
+
+ attr_field_obj = bt_ctf_private_value_array_borrow_element_by_index(
+ 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_ctf_private_value_array_borrow_element_by_index(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_ctf_private_value *bt_ctf_attributes_borrow_field_by_name(
+ struct bt_ctf_private_value *attr_obj, const char *name)
+{
+ uint64_t i;
+ int64_t attr_size;
+ struct bt_ctf_private_value *value_obj = NULL;
+ struct bt_ctf_private_value *attr_field_name_obj = NULL;
+
+ attr_size = bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(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) {
+ const char *field_name;
+
+ value_obj = bt_ctf_private_value_array_borrow_element_by_index(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_ctf_private_value_array_borrow_element_by_index(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;
+ }
+
+ field_name = bt_ctf_value_string_get(
+ bt_ctf_private_value_as_value(attr_field_name_obj));
+
+ 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_ctf_private_value *attr_obj,
+ const char *name, struct bt_ctf_private_value *value_obj)
+{
+ int ret = 0;
+ struct bt_ctf_private_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_ctf_private_value_array_set_element_by_index(
+ attr_field_obj, BT_CTF_ATTR_VALUE_INDEX,
+ bt_ctf_private_value_as_value(value_obj));
+ attr_field_obj = NULL;
+ goto end;
+ }
+
+ attr_field_obj = bt_ctf_private_value_array_create();
+ if (!attr_field_obj) {
+ BT_LOGE_STR("Failed to create empty array value.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_private_value_array_append_string_element(attr_field_obj, name);
+ ret |= bt_ctf_private_value_array_append_element(attr_field_obj,
+ bt_ctf_private_value_as_value(value_obj));
+ if (ret) {
+ BT_LOGE("Cannot append elements to array value: addr=%p",
+ attr_field_obj);
+ goto end;
+ }
+
+ ret = bt_ctf_private_value_array_append_element(attr_obj,
+ bt_ctf_private_value_as_value(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_ctf_object_put_ref(attr_field_obj);
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_attributes_borrow_field_value_by_name(
+ struct bt_ctf_private_value *attr_obj, const char *name)
+{
+ struct bt_ctf_private_value *value_obj = NULL;
+ struct bt_ctf_private_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_ctf_private_value_array_borrow_element_by_index(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_ctf_private_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_ctf_value_array_get_size(bt_ctf_private_value_as_value(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_ctf_private_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_ctf_value_freeze(bt_ctf_private_value_as_value(obj));
+ }
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/compat/uuid-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/compat/string-internal.h>
+#include <inttypes.h>
+#include <babeltrace2/ctf-writer/object-internal.h>
+#include <babeltrace2/assert-internal.h>
+
+static
+void bt_ctf_clock_class_destroy(struct bt_ctf_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_ctf_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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_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;
+}
--- /dev/null
+/*
+ * clock.c
+ *
+ * Babeltrace CTF writer - Clock
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017 Philippe Proulx <pproulx@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"
+#include "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compat/uuid-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/ctf-writer/object-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <inttypes.h>
+
+static
+void bt_ctf_clock_destroy(struct bt_ctf_object *obj);
+
+struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
+{
+ int ret;
+ struct bt_ctf_clock *clock = NULL;
+ unsigned char cc_uuid[BABELTRACE_UUID_LEN];
+
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
+ clock = g_new0(struct bt_ctf_clock, 1);
+ if (!clock) {
+ goto error;
+ }
+
+ bt_ctf_object_init_shared(&clock->base, bt_ctf_clock_destroy);
+ clock->value = 0;
+
+ /* Pre-2.0.0 backward compatibility: default frequency is 1 GHz */
+ clock->clock_class = (void *) bt_ctf_clock_class_create(name, 1000000000);
+ if (!clock->clock_class) {
+ goto error;
+ }
+
+ /* Automatically set clock class's UUID. */
+ ret = bt_uuid_generate(cc_uuid);
+ if (ret) {
+ goto error;
+ }
+
+ ret = bt_ctf_clock_class_set_uuid(clock->clock_class, cc_uuid);
+ BT_ASSERT(ret == 0);
+ return clock;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(clock);
+ return clock;
+}
+
+const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ return bt_ctf_clock_class_get_name(clock->clock_class);
+}
+
+const char *bt_ctf_clock_get_description(struct bt_ctf_clock *clock)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ return bt_ctf_clock_class_set_description(clock->clock_class,
+ desc);
+}
+
+uint64_t bt_ctf_clock_get_frequency(struct bt_ctf_clock *clock)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ return bt_ctf_clock_class_set_frequency(clock->clock_class,
+ freq);
+}
+
+uint64_t bt_ctf_clock_get_precision(struct bt_ctf_clock *clock)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ 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_ctf_clock_class *cc;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ cc = clock->clock_class;
+
+ /* Common case where cycles are actually nanoseconds */
+ if (cc->frequency == 1000000000) {
+ value = time;
+ } else {
+ value = (uint64_t) (((double) time *
+ (double) cc->frequency) / 1e9);
+ }
+
+ BT_CTF_ASSERT_PRE(clock->value <= value,
+ "CTF writer clock value must be updated monotonically: "
+ "prev-value=%" PRId64 ", new-value=%" PRId64,
+ clock->value, value);
+ clock->value = value;
+ return 0;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ *value = clock->value;
+ return 0;
+}
+
+static
+void bt_ctf_clock_destroy(struct bt_ctf_object *obj)
+{
+ struct bt_ctf_clock *clock;
+
+ clock = container_of(obj, struct bt_ctf_clock, base);
+ bt_ctf_object_put_ref(clock->clock_class);
+ g_free(clock);
+}
+
+BT_HIDDEN
+void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
+ struct metadata_context *context)
+{
+ unsigned char *uuid;
+
+ BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
+ "name=\"%s\", metadata-context-addr=%p", clock_class,
+ bt_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_ctf_clock_class_get_name(clock_class),
+ context);
+ return;
+ }
+
+ uuid = clock_class->uuid;
+ g_string_append(context->string, "clock {\n");
+ g_string_append_printf(context->string, "\tname = %s;\n",
+ clock_class->name->str);
+
+ if (clock_class->uuid_set) {
+ g_string_append_printf(context->string,
+ "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ }
+
+ if (clock_class->description) {
+ g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
+ clock_class->description->str);
+ }
+
+ g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
+ clock_class->frequency);
+ g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
+ clock_class->precision);
+ g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
+ clock_class->offset_s);
+ g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
+ clock_class->offset);
+ g_string_append_printf(context->string, "\tabsolute = %s;\n",
+ clock_class->absolute ? "true" : "false");
+ g_string_append(context->string, "};\n\n");
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-EVENT-CLASS"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/attributes-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/event-internal.h>
+#include <babeltrace2/ctf-writer/event.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/stream-class.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/validation-internal.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/ctf-writer/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_ctf_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_ctf_object_put_ref(event_class->context_field_type);
+ BT_LOGD_STR("Putting payload field type.");
+ bt_ctf_object_put_ref(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_ctf_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_ctf_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_ctf_object *obj)
+{
+ bt_ctf_event_class_common_finalize(obj);
+ g_free(obj);
+}
+
+struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
+{
+ struct bt_ctf_event_class *ctf_event_class = NULL;
+ int ret;
+
+ if (!name) {
+ BT_LOGW_STR("Invalid parameter: name is NULL.");
+ goto error;
+ }
+
+ BT_LOGD("Creating event class object: name=\"%s\"",
+ name);
+ ctf_event_class = g_new0(struct bt_ctf_event_class, 1);
+ if (!ctf_event_class) {
+ BT_LOGE_STR("Failed to allocate one event class.");
+ goto error;
+ }
+
+ ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class),
+ name, bt_ctf_event_class_destroy,
+ (bt_ctf_field_type_structure_create_func)
+ bt_ctf_field_type_structure_create);
+ if (ret) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ bt_ctf_object_put_ref(ctf_event_class);
+
+end:
+ return ctf_event_class;
+}
+
+const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
+{
+ return bt_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_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_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_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_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_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_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
+ emf_uri);
+}
+
+struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
+ struct bt_ctf_event_class *event_class)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ return bt_ctf_object_get_ref(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_ctf_object_get_ref(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_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_ctf_object_get_ref(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_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,
+ struct bt_ctf_field_type *type,
+ const char *name)
+{
+ int ret = 0;
+
+ if (!event_class || !type) {
+ BT_LOGW("Invalid parameter: event class or field type is NULL: "
+ "event-class-addr=%p, field-type-addr=%p",
+ event_class, type);
+ ret = -1;
+ goto end;
+ }
+
+ if (!bt_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),
+ bt_ctf_event_class_get_id(event_class),
+ name);
+ ret = -1;
+ goto end;
+ }
+
+ if (event_class->common.frozen) {
+ BT_LOGW("Invalid parameter: event class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ ret = -1;
+ goto end;
+ }
+
+ if (!event_class->common.payload_field_type) {
+ BT_LOGW("Event class has no payload field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ ret = -1;
+ goto end;
+ }
+
+ BT_ASSERT(bt_ctf_field_type_common_get_type_id(
+ event_class->common.payload_field_type) ==
+ BT_CTF_FIELD_TYPE_ID_STRUCT);
+ ret = bt_ctf_field_type_structure_add_field(
+ (void *) event_class->common.payload_field_type,
+ (void *) type, name);
+ BT_LOGV("Added field to event class's payload field type: "
+ "event-class-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p",
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class), name, type);
+end:
+ return ret;
+}
+
+int64_t bt_ctf_event_class_get_payload_type_field_count(
+ struct bt_ctf_event_class *event_class)
+{
+ int64_t ret;
+
+ if (!event_class) {
+ BT_LOGW_STR("Invalid parameter: event class is NULL.");
+ ret = (int64_t) -1;
+ goto end;
+ }
+
+ if (!event_class->common.payload_field_type) {
+ BT_LOGV("Event class has no payload field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ ret = (int64_t) -1;
+ goto end;
+ }
+
+ BT_ASSERT(bt_ctf_field_type_common_get_type_id(
+ event_class->common.payload_field_type) ==
+ 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;
+}
+
+int bt_ctf_event_class_get_payload_type_field_by_index(
+ struct bt_ctf_event_class *event_class,
+ const char **field_name, struct bt_ctf_field_type **field_type,
+ uint64_t index)
+{
+ int ret;
+
+ if (!event_class) {
+ BT_LOGW_STR("Invalid parameter: event class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!event_class->common.payload_field_type) {
+ BT_LOGV("Event class has no payload field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64,
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class), index);
+ ret = -1;
+ goto end;
+ }
+
+ BT_ASSERT(bt_ctf_field_type_common_get_type_id(
+ event_class->common.payload_field_type) ==
+ 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);
+
+end:
+ return ret;
+}
+
+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_ctf_field_type *field_type = NULL;
+
+ if (!event_class || !name) {
+ BT_LOGW("Invalid parameter: event class or name is NULL: "
+ "event-class-addr=%p, name-addr=%p",
+ event_class, name);
+ goto end;
+ }
+
+ if (!event_class->common.payload_field_type) {
+ BT_LOGV("Event class has no payload field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ goto end;
+ }
+
+ BT_ASSERT(bt_ctf_field_type_common_get_type_id(
+ event_class->common.payload_field_type) ==
+ BT_CTF_FIELD_TYPE_ID_STRUCT);
+ name_quark = g_quark_try_string(name);
+ if (!name_quark) {
+ BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
+ goto end;
+ }
+
+ /*
+ * No need to increment field_type's reference count since getting it
+ * from the structure already does.
+ */
+ field_type = (void *)
+ bt_ctf_field_type_structure_get_field_type_by_name(
+ (void *) event_class->common.payload_field_type, name);
+
+end:
+ return field_type;
+}
+
+BT_HIDDEN
+int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
+ struct metadata_context *context)
+{
+ int ret = 0;
+ struct bt_ctf_value *attr_value = NULL;
+
+ BT_ASSERT(event_class);
+ BT_ASSERT(context);
+ BT_LOGD("Serializing event class's metadata: "
+ "event-class-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64 ", metadata-context-addr=%p",
+ event_class, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class), context);
+ context->current_indentation_level = 1;
+ g_string_assign(context->field_name, "");
+ g_string_append(context->string, "event {\n");
+
+ /* Serialize attributes */
+ g_string_append_printf(context->string, "\tname = \"%s\";\n",
+ event_class->common.name->str);
+ BT_ASSERT(event_class->common.id >= 0);
+ g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
+ event_class->common.id);
+ g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
+ bt_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_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
+ g_string_append_printf(context->string, "\tloglevel = %d;\n",
+ (int) event_class->common.log_level);
+ }
+
+ if (event_class->common.emf_uri->len > 0) {
+ g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
+ event_class->common.emf_uri->str);
+ }
+
+ /* Serialize context field type */
+ if (event_class->common.context_field_type) {
+ g_string_append(context->string, "\tcontext := ");
+ BT_LOGD_STR("Serializing event class's context field type metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) event_class->common.context_field_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize event class's context field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";\n");
+ }
+
+ /* Serialize payload field type */
+ if (event_class->common.payload_field_type) {
+ g_string_append(context->string, "\tfields := ");
+ BT_LOGD_STR("Serializing event class's payload field type metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) event_class->common.payload_field_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize event class's payload field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";\n");
+ }
+
+ g_string_append(context->string, "};\n\n");
+
+end:
+ context->current_indentation_level = 0;
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
+ return ret;
+}
+
+struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
+ struct bt_ctf_event_class *event_class, const char *name)
+{
+ GQuark name_quark;
+ struct bt_ctf_field_type *field_type = NULL;
+
+ if (!event_class || !name) {
+ BT_LOGW("Invalid parameter: event class or name is NULL: "
+ "event-class-addr=%p, name-addr=%p",
+ event_class, name);
+ goto end;
+ }
+
+ if (!event_class->common.payload_field_type) {
+ BT_LOGV("Event class has no payload field type: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ event_class,
+ bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ goto end;
+ }
+
+ BT_ASSERT(event_class->common.payload_field_type->id ==
+ BT_CTF_FIELD_TYPE_ID_STRUCT);
+ name_quark = g_quark_try_string(name);
+ if (!name_quark) {
+ BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
+ goto end;
+ }
+
+ /*
+ * No need to increment field_type's reference count since getting it
+ * from the structure already does.
+ */
+ field_type = bt_ctf_object_get_ref(
+ bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+ event_class->common.payload_field_type, name));
+
+end:
+ return field_type;
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-EVENT"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/attributes-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/event-internal.h>
+#include <babeltrace2/ctf-writer/event.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/fields.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/stream-class.h>
+#include <babeltrace2/ctf-writer/stream-internal.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/trace.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/validation-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <inttypes.h>
+
+static
+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_ctf_private_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 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_CTF_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_CTF_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_CTF_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_CTF_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_ctf_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_ctf_object_get_ref(init_expected_clock_class) :
+ NULL;
+
+ BT_CTF_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_CTF_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_CTF_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_ctf_object_init_shared_with_parent(&event->base, release_func);
+ } else {
+ bt_ctf_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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(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_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.");
+ }
+
+ return ret;
+}
+
+static
+void destroy_event_header_field(struct bt_ctf_field_wrapper *field_wrapper)
+{
+ BT_ASSERT(field_wrapper);
+ bt_ctf_object_put_ref(field_wrapper->field);
+ bt_ctf_field_wrapper_destroy(field_wrapper);
+}
+
+static
+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_ctf_field_wrapper *field_wrapper = NULL;
+ struct bt_ctf_field *field = bt_ctf_field_create((void *) ft);
+
+ if (!field) {
+ goto error;
+ }
+
+ field_wrapper = bt_ctf_field_wrapper_new(NULL);
+ if (!field_wrapper) {
+ goto error;
+ }
+
+ field_wrapper->field = (void *) field;
+ field = NULL;
+ goto end;
+
+error:
+ bt_ctf_object_put_ref(field);
+
+ if (field_wrapper) {
+ destroy_event_header_field(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+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_CTF_OBJECT_PUT_REF_AND_RESET(field_wrapper->field);
+ bt_ctf_field_wrapper_destroy(field_wrapper);
+}
+
+static
+void bt_ctf_event_destroy(struct bt_ctf_object *obj)
+{
+ bt_ctf_event_common_finalize(obj, (void *) bt_ctf_object_put_ref,
+ (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_ctf_clock_class *expected_clock_class = NULL;
+
+ event = g_new0(struct bt_ctf_event, 1);
+ if (!event) {
+ BT_LOGE_STR("Failed to allocate one CTF writer event.");
+ goto error;
+ }
+
+ if (event_class) {
+ struct bt_ctf_stream_class *stream_class =
+ BT_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 = stream_class->clock->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_ctf_validation_flag_copy_field_type_func)
+ bt_ctf_field_type_copy,
+ false, map_clock_classes_func,
+ (create_field_func) bt_ctf_field_create,
+ (release_field_func) bt_ctf_object_put_ref,
+ (create_header_field_func) create_event_header_field,
+ (release_header_field_func) destroy_event_header_field);
+ if (ret) {
+ /* bt_ctf_event_common_initialize() logs errors */
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(event);
+
+end:
+ return event;
+}
+
+struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ return bt_ctf_object_get_ref(bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event)));
+}
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_event_borrow_stream(struct bt_ctf_event *event)
+{
+ BT_ASSERT(event);
+ return (struct bt_ctf_stream *)
+ bt_ctf_object_borrow_parent(&BT_CTF_TO_COMMON(event)->base);
+}
+
+struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ return bt_ctf_object_get_ref(bt_ctf_event_borrow_stream(event));
+}
+
+int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name,
+ struct bt_ctf_field *field)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Payload field");
+ BT_CTF_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);
+}
+
+struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
+ const char *name)
+{
+ struct bt_ctf_field *field = NULL;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+
+ if (name) {
+ field = bt_ctf_field_structure_get_field_by_name(
+ BT_CTF_FROM_COMMON(event->common.payload_field), name);
+ } else {
+ field = BT_CTF_FROM_COMMON(event->common.payload_field);
+ bt_ctf_object_get_ref(field);
+ }
+
+ return field;
+}
+
+struct bt_ctf_field *bt_ctf_event_get_payload_field(
+ struct bt_ctf_event *event)
+{
+ return bt_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(bt_ctf_event_common_borrow_stream_event_context(
+ BT_CTF_TO_COMMON(event)));
+}
+
+BT_HIDDEN
+int bt_ctf_event_serialize(struct bt_ctf_event *event,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int ret = 0;
+
+ BT_ASSERT(event);
+ BT_ASSERT(ctfser);
+
+ BT_LOGV_STR("Serializing event's context field.");
+ if (event->common.context_field) {
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) event->common.context_field, ctfser,
+ native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize event's context field: "
+ "event-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64,
+ event,
+ bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class));
+ goto end;
+ }
+ }
+
+ BT_LOGV_STR("Serializing event's payload field.");
+ if (event->common.payload_field) {
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) event->common.payload_field, ctfser,
+ native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize event's payload field: "
+ "event-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64,
+ event,
+ bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class));
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+void _bt_ctf_event_freeze(struct bt_ctf_event *event)
+{
+ _bt_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_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_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_CTF_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-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_CTF_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-addr=%p, header-ft-addr=%p",
+ event,
+ bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
+ }
+
+ bt_ctf_object_put_ref(event->common.header_field->field);
+ event->common.header_field->field = bt_ctf_object_get_ref(header);
+ BT_LOGV("Set event's header field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "header-field-addr=%p",
+ event, bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class), header);
+ return 0;
+}
+
+int bt_ctf_event_common_set_payload(struct bt_ctf_event *event,
+ struct bt_ctf_field *payload)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
+
+ if (payload) {
+ BT_CTF_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-addr=%p, ft-addr=%p, "
+ "expected-ft-addr=%p",
+ event,
+ ((struct bt_ctf_field_common *) payload)->type,
+ event->common.class->payload_field_type);
+ } else {
+ BT_CTF_ASSERT_PRE(!event->common.class->payload_field_type,
+ "Setting no event payload field, "
+ "but event payload field type is not NULL: "
+ "event-addr=%p, payload-ft-addr=%p",
+ event, event->common.class->payload_field_type);
+ }
+
+ bt_ctf_object_put_ref(event->common.payload_field);
+ event->common.payload_field = bt_ctf_object_get_ref(payload);
+ BT_LOGV("Set event's payload field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "payload-field-addr=%p",
+ event, bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class), payload);
+ return 0;
+}
+
+int bt_ctf_event_set_context(struct bt_ctf_event *event,
+ struct bt_ctf_field *context)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
+
+ if (context) {
+ BT_CTF_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-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_CTF_ASSERT_PRE(!event->common.class->context_field_type,
+ "Setting no event context field, "
+ "but event context field type is not NULL: "
+ "event-addr=%p, context-ft-addr=%p",
+ event, event->common.class->context_field_type);
+ }
+
+ bt_ctf_object_put_ref(event->common.context_field);
+ event->common.context_field = bt_ctf_object_get_ref(context);
+ BT_LOGV("Set event's context field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "context-field-addr=%p",
+ event, bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class), context);
+ return 0;
+}
+
+int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
+ struct bt_ctf_field *stream_event_context)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
+
+ if (stream_event_context) {
+ BT_CTF_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-addr=%p, ft-addr=%p, "
+ "expected-ft-addr=%p",
+ event,
+ ((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_CTF_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-addr=%p, context-ft-addr=%p",
+ event,
+ bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
+ }
+
+ bt_ctf_object_put_ref(event->common.stream_event_context_field);
+ event->common.stream_event_context_field = bt_ctf_object_get_ref(stream_event_context);
+ BT_LOGV("Set event's stream event context field: event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+ "stream-event-context-field-addr=%p",
+ event, bt_ctf_event_class_common_get_name(event->common.class),
+ bt_ctf_event_class_common_get_id(event->common.class),
+ stream_event_context);
+ return 0;
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/ctf-writer/field-path-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdint.h>
+
+static
+void field_path_destroy(struct bt_ctf_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_ctf_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_CTF_OBJECT_PUT_REF_AND_RESET(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;
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-FIELD-TYPES"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/ctf-writer/field-path-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/fields.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object-internal.h>
+#include <babeltrace2/ctf-writer/object.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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_put_ref(ft->mapped_clock_class);
+ g_free(ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_floating_point_destroy(struct bt_ctf_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_ctf_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_ctf_object_put_ref(ft->container_ft);
+ g_free(ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_string_destroy(struct bt_ctf_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_ctf_object_put_ref(field->type);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_destroy_recursive(struct bt_ctf_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_ctf_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_ctf_object_put_ref(ft->element_ft);
+ g_free(ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_destroy_recursive(struct bt_ctf_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_ctf_object_put_ref(ft->element_ft);
+ g_string_free(ft->length_field_name, TRUE);
+ BT_LOGD_STR("Putting length field path.");
+ bt_ctf_object_put_ref(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_ctf_object_put_ref(choice->type);
+
+ if (choice->ranges) {
+ g_array_free(choice->ranges, TRUE);
+ }
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_destroy_recursive(struct bt_ctf_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_ctf_object_put_ref(ft->tag_ft);
+ BT_LOGD_STR("Putting tag field path.");
+ bt_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_ctf_object_put_ref(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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_ctf_object_init_shared(&iter->base, bt_ctf_field_type_enum_iter_destroy);
+ iter->enumeration_ft = bt_ctf_object_get_ref(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_ctf_object_put_ref(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_CTF_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_ctf_object_put_ref(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_ctf_object_put_ref(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_CTF_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_ctf_object_put_ref(int_ft->mapped_clock_class);
+ int_ft->mapped_clock_class = bt_ctf_object_get_ref(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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_ctf_object_put_ref(field->type);
+ field->type = bt_ctf_object_get_ref(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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
+ "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_NON_NULL(field_name, "Name");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Variant field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+ "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_OBJECT_PUT_REF_AND_RESET(array_ft->element_ft);
+ }
+
+ array_ft->element_ft = bt_ctf_object_get_ref(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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_OBJECT_PUT_REF_AND_RESET(seq_ft->element_ft);
+ }
+
+ seq_ft->element_ft = element_ft;
+ bt_ctf_object_get_ref(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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_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_CTF_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_CTF_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_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_CTF_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_ctf_object_get_ref(path);
+ BT_CTF_OBJECT_MOVE_REF(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_ctf_object_get_ref(path);
+ BT_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(var_ft->tag_ft);
+ var_ft->tag_ft = bt_ctf_object_get_ref(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_ctf_object_put_ref(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_CTF_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_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_ctf_object_get_ref(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_ctf_object_put_ref(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);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
+ struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
+ struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
+ struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
+ struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
+ struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
+ struct bt_ctf_field_type *type);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_string_copy(
+ struct bt_ctf_field_type *type);
+
+static struct bt_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_ctf_field_type_common_integer_compare,
+};
+
+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_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_ctf_field_type_common_floating_point_compare,
+};
+
+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_ctf_field_type_common_enumeration_compare_recursive,
+};
+
+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_ctf_field_type_common_method_copy)
+ bt_ctf_field_type_string_copy,
+ .compare = bt_ctf_field_type_common_string_compare,
+};
+
+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_ctf_field_type_common_array_compare_recursive,
+};
+
+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_ctf_field_type_common_sequence_compare_recursive,
+};
+
+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_ctf_field_type_common_structure_compare_recursive,
+};
+
+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_ctf_field_type_common_variant_compare_recursive,
+};
+
+typedef int (*bt_ctf_field_type_serialize_func)(struct bt_ctf_field_type_common *,
+ struct metadata_context *);
+
+BT_HIDDEN
+int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
+ struct metadata_context *context)
+{
+ int ret;
+ struct bt_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_ctf_field_type_common_validate((void *) type);
+ if (ret) {
+ BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
+ "addr=%p", type);
+ goto end;
+ }
+
+ serialize_func = type_common->spec.writer.serialize_func;
+ ret = serialize_func((void *) type, context);
+
+end:
+ return ret;
+}
+
+static
+const char *get_encoding_string(enum bt_ctf_string_encoding encoding)
+{
+ const char *encoding_string;
+
+ switch (encoding) {
+ case BT_CTF_STRING_ENCODING_NONE:
+ encoding_string = "none";
+ break;
+ case BT_CTF_STRING_ENCODING_ASCII:
+ encoding_string = "ASCII";
+ break;
+ case BT_CTF_STRING_ENCODING_UTF8:
+ encoding_string = "UTF8";
+ break;
+ default:
+ encoding_string = "unknown";
+ break;
+ }
+
+ return encoding_string;
+}
+
+static
+const char *get_integer_base_string(enum bt_ctf_integer_base base)
+{
+ const char *base_string;
+
+ switch (base) {
+ case BT_CTF_INTEGER_BASE_DECIMAL:
+ case BT_CTF_INTEGER_BASE_UNSPECIFIED:
+ base_string = "decimal";
+ break;
+ case BT_CTF_INTEGER_BASE_HEXADECIMAL:
+ base_string = "hexadecimal";
+ break;
+ case BT_CTF_INTEGER_BASE_OCTAL:
+ base_string = "octal";
+ break;
+ case BT_CTF_INTEGER_BASE_BINARY:
+ base_string = "binary";
+ break;
+ default:
+ base_string = "unknown";
+ break;
+ }
+
+ return base_string;
+}
+
+static
+void append_field_name(struct metadata_context *context,
+ const char *name)
+{
+ g_string_append_c(context->string, ' ');
+
+ if (!bt_ctf_identifier_is_valid(name) || *name == '_') {
+ g_string_append_c(context->string, '_');
+ }
+
+ g_string_append(context->string, name);
+}
+
+static
+int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ 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: "
+ "ft-addr=%p, metadata-context-addr=%p", type, context);
+ g_string_append_printf(context->string,
+ "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
+ integer->size, type->alignment,
+ (integer->is_signed ? "true" : "false"),
+ get_encoding_string(integer->encoding),
+ get_integer_base_string(integer->base),
+ bt_ctf_get_byte_order_string(integer->user_byte_order));
+ if (integer->mapped_clock_class) {
+ const char *clock_name = bt_ctf_clock_class_get_name(
+ integer->mapped_clock_class);
+
+ BT_ASSERT(clock_name);
+ g_string_append_printf(context->string,
+ "; map = clock.%s.value", clock_name);
+ }
+
+ g_string_append(context->string, "; }");
+ return ret;
+}
+
+static
+int bt_ctf_field_type_enumeration_serialize_recursive(
+ struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ size_t entry;
+ int ret;
+ 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_ctf_field_type_common_enumeration_borrow_container_field_type(type);
+ BT_ASSERT(container_type);
+ container_signed = bt_ctf_field_type_common_integer_is_signed(
+ container_type);
+ BT_ASSERT(container_signed >= 0);
+ g_string_append(context->string, "enum : ");
+ BT_LOGD_STR("Serializing CTF writer enumeration field type's container field type's metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) enumeration->container_ft, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize CTF writer enumeration field type's container field type's metadata: "
+ "container-ft-addr=%p", enumeration->container_ft);
+ goto end;
+ }
+
+ g_string_append(context->string, " { ");
+ for (entry = 0; entry < enumeration->entries->len; entry++) {
+ struct 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_ctf_identifier_is_valid(label) || label[0] == '_') {
+ g_string_append(context->string, "_");
+ }
+
+ g_string_append_printf(context->string, "%s\" = ", label);
+
+ if (container_signed) {
+ if (mapping->range_start._signed ==
+ mapping->range_end._signed) {
+ g_string_append_printf(context->string,
+ "%" PRId64,
+ mapping->range_start._signed);
+ } else {
+ g_string_append_printf(context->string,
+ "%" PRId64 " ... %" PRId64,
+ mapping->range_start._signed,
+ mapping->range_end._signed);
+ }
+ } else {
+ if (mapping->range_start._unsigned ==
+ mapping->range_end._unsigned) {
+ g_string_append_printf(context->string,
+ "%" PRIu64,
+ mapping->range_start._unsigned);
+ } else {
+ g_string_append_printf(context->string,
+ "%" PRIu64 " ... %" PRIu64,
+ mapping->range_start._unsigned,
+ mapping->range_end._unsigned);
+ }
+ }
+
+ g_string_append(context->string,
+ ((entry != (enumeration->entries->len - 1)) ?
+ ", " : " }"));
+ }
+
+ if (context->field_name->len) {
+ append_field_name(context,
+ context->field_name->str);
+ g_string_assign(context->field_name, "");
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ 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);
+ g_string_append_printf(context->string,
+ "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
+ floating_point->exp_dig,
+ floating_point->mant_dig,
+ 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_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ size_t i;
+ unsigned int indent;
+ int ret = 0;
+ 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: "
+ "ft-addr=%p, metadata-context-addr=%p", type, context);
+ context->field_name = g_string_new("");
+
+ context->current_indentation_level++;
+ g_string_append(context->string, "struct {\n");
+
+ for (i = 0; i < structure->fields->len; i++) {
+ struct 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: "
+ "index=%zu, "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, field, g_quark_to_string(field->name));
+
+ for (indent = 0; indent < context->current_indentation_level;
+ indent++) {
+ g_string_append_c(context->string, '\t');
+ }
+
+ g_string_assign(context->field_name,
+ g_quark_to_string(field->name));
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) field->type, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize CTF writer structure field type's field's metadata: "
+ "index=%zu, "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, field->type,
+ g_quark_to_string(field->name));
+ goto end;
+ }
+
+ if (context->field_name->len) {
+ append_field_name(context,
+ context->field_name->str);
+ }
+ g_string_append(context->string, ";\n");
+ }
+
+ context->current_indentation_level--;
+ for (indent = 0; indent < context->current_indentation_level;
+ indent++) {
+ g_string_append_c(context->string, '\t');
+ }
+
+ g_string_append_printf(context->string, "} align(%u)",
+ type->alignment);
+
+end:
+ g_string_free(context->field_name, TRUE);
+ context->field_name = structure_field_name;
+ return ret;
+}
+
+static
+int bt_ctf_field_type_variant_serialize_recursive(
+ struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ size_t i;
+ unsigned int indent;
+ int ret = 0;
+ 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: "
+ "ft-addr=%p, metadata-context-addr=%p", type, context);
+ context->field_name = g_string_new("");
+ if (variant->tag_name->len > 0) {
+ g_string_append(context->string, "variant <");
+ append_field_name(context, variant->tag_name->str);
+ g_string_append(context->string, "> {\n");
+ } else {
+ g_string_append(context->string, "variant {\n");
+ }
+
+ context->current_indentation_level++;
+ for (i = 0; i < variant->choices->len; i++) {
+ 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: "
+ "index=%zu, "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, field, g_quark_to_string(field->name));
+
+ g_string_assign(context->field_name,
+ g_quark_to_string(field->name));
+ for (indent = 0; indent < context->current_indentation_level;
+ indent++) {
+ g_string_append_c(context->string, '\t');
+ }
+
+ g_string_assign(context->field_name,
+ g_quark_to_string(field->name));
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) field->type, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize CTF writer variant field type's field's metadata: "
+ "index=%zu, "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, field->type,
+ g_quark_to_string(field->name));
+ goto end;
+ }
+
+ if (context->field_name->len) {
+ append_field_name(context,
+ context->field_name->str);
+ g_string_append_c(context->string, ';');
+ }
+
+ g_string_append_c(context->string, '\n');
+ }
+
+ context->current_indentation_level--;
+ for (indent = 0; indent < context->current_indentation_level;
+ indent++) {
+ g_string_append_c(context->string, '\t');
+ }
+
+ g_string_append(context->string, "}");
+
+end:
+ g_string_free(context->field_name, TRUE);
+ context->field_name = variant_field_name;
+ return ret;
+}
+
+static
+int bt_ctf_field_type_array_serialize_recursive(
+ struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ int ret = 0;
+ 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);
+ BT_LOGD_STR("Serializing CTF writer array field type's element field type's metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) array->element_ft, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize CTF writer array field type's element field type's metadata: "
+ "element-ft-addr=%p", array->element_ft);
+ goto end;
+ }
+
+ if (context->field_name->len) {
+ append_field_name(context,
+ context->field_name->str);
+
+ g_string_append_printf(context->string, "[%u]", array->length);
+ g_string_assign(context->field_name, "");
+ } else {
+ g_string_append_printf(context->string, "[%u]", array->length);
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_type_sequence_serialize_recursive(
+ struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ int ret = 0;
+ 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);
+ BT_LOGD_STR("Serializing CTF writer sequence field type's element field type's metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) sequence->element_ft, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize CTF writer sequence field type's element field type's metadata: "
+ "element-ft-addr=%p", sequence->element_ft);
+ goto end;
+ }
+
+ if (context->field_name->len) {
+ append_field_name(context, context->field_name->str);
+ g_string_assign(context->field_name, "");
+ }
+ g_string_append(context->string, "[");
+ append_field_name(context, sequence->length_field_name->str);
+ g_string_append(context->string, "]");
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type_common *type,
+ struct metadata_context *context)
+{
+ 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);
+ g_string_append_printf(context->string,
+ "string { encoding = %s; }",
+ get_encoding_string(string->encoding));
+ return 0;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
+{
+ struct bt_ctf_field_type_common_integer *integer = NULL;
+
+ BT_LOGD("Creating CTF writer integer field type object: size=%u", size);
+
+ if (size == 0 || size > 64) {
+ BT_LOGW("Invalid parameter: size must be between 1 and 64: "
+ "size=%u", size);
+ goto error;
+ }
+
+ integer = g_new0(struct bt_ctf_field_type_common_integer, 1);
+ if (!integer) {
+ BT_LOGE_STR("Failed to allocate one integer field type.");
+ goto error;
+ }
+
+ 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;
+ BT_LOGD("Created CTF writer integer field type object: addr=%p, size=%u",
+ integer, size);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(integer);
+
+end:
+ return (void *) integer;
+}
+
+int bt_ctf_field_type_integer_get_size(struct bt_ctf_field_type *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_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_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_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_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_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_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_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_ctf_object_get_ref(bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
+ (void *) ft));
+}
+
+int bt_ctf_field_type_integer_set_mapped_clock_class(
+ struct bt_ctf_field_type *ft,
+ struct bt_ctf_clock_class *clock_class)
+{
+ return bt_ctf_field_type_common_integer_set_mapped_clock_class((void *) ft,
+ clock_class);
+}
+
+int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
+ struct bt_ctf_field_type *ft, uint64_t index,
+ const char **mapping_name, int64_t *range_begin,
+ int64_t *range_end)
+{
+ return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
+ (void *) ft, index, mapping_name, range_begin, range_end);
+}
+
+int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
+ struct bt_ctf_field_type *ft, uint64_t index,
+ const char **mapping_name, uint64_t *range_begin,
+ uint64_t *range_end)
+{
+ return bt_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_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);
+
+ if (!container_ft) {
+ BT_LOGW_STR("Invalid parameter: field type is NULL.");
+ goto error;
+ }
+
+ 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_ctf_field_type_id_string(int_ft->id));
+ goto error;
+ }
+
+ 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_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;
+ BT_LOGD("Created CTF writer enumeration field type object: addr=%p, "
+ "int-ft-addr=%p, int-ft-size=%u",
+ enumeration, container_ft,
+ bt_ctf_field_type_integer_get_size(container_ft));
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(enumeration);
+
+end:
+ return (void *) enumeration;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type(
+ struct bt_ctf_field_type *ft)
+{
+ return bt_ctf_object_get_ref(
+ bt_ctf_field_type_common_enumeration_borrow_container_field_type(
+ (void *) ft));
+}
+
+int bt_ctf_field_type_enumeration_signed_add_mapping(
+ struct bt_ctf_field_type *ft, const char *string,
+ int64_t range_start, int64_t range_end)
+{
+ return bt_ctf_field_type_common_enumeration_signed_add_mapping(
+ (void *) ft, string, range_start, range_end);
+}
+
+int bt_ctf_field_type_enumeration_unsigned_add_mapping(
+ struct bt_ctf_field_type *ft, const char *string,
+ uint64_t range_start, uint64_t range_end)
+{
+ return bt_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_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_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.");
+
+ if (!floating_point) {
+ BT_LOGE_STR("Failed to allocate one floating point number field type.");
+ goto end;
+ }
+
+ 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;
+ BT_LOGD("Created CTF writer floating point number field type object: addr=%p, "
+ "exp-size=%u, mant-size=%u", floating_point,
+ floating_point->exp_dig, floating_point->mant_dig);
+
+end:
+ return (void *) floating_point;
+}
+
+int bt_ctf_field_type_floating_point_get_exponent_digits(
+ struct bt_ctf_field_type *ft)
+{
+ return bt_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_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_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_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_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.");
+
+ if (!structure) {
+ BT_LOGE_STR("Failed to allocate one structure field type.");
+ goto error;
+ }
+
+ 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;
+ BT_LOGD("Created CTF writer structure field type object: addr=%p",
+ structure);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(structure);
+
+end:
+ return (void *) structure;
+}
+
+int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *ft,
+ struct bt_ctf_field_type *field_type,
+ const char *field_name)
+{
+ return bt_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_ctf_field_type_common_structure_get_field_count((void *) ft);
+}
+
+int bt_ctf_field_type_structure_get_field_by_index(
+ struct bt_ctf_field_type *ft,
+ const char **field_name,
+ struct bt_ctf_field_type **field_type, uint64_t index)
+{
+ 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) {
+ bt_ctf_object_get_ref(*field_type);
+ }
+
+ return ret;
+}
+
+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_ctf_object_get_ref(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_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_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_ctf_field_type_common_variant, 1);
+ if (!var_ft) {
+ BT_LOGE_STR("Failed to allocate one variant field type.");
+ goto error;
+ }
+
+ bt_ctf_field_type_common_variant_initialize(BT_CTF_TO_COMMON(var_ft),
+ (void *) tag_ft, tag_name,
+ 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;
+ BT_LOGD("Created CTF writer variant field type object: addr=%p, "
+ "tag-ft-addr=%p, tag-field-name=\"%s\"",
+ var_ft, tag_ft, tag_name);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(var_ft);
+
+end:
+ return (void *) var_ft;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
+ struct bt_ctf_field_type *ft)
+{
+ return bt_ctf_object_get_ref(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_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_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_ctf_field_type_common_variant_add_field((void *) ft,
+ (void *) field_type, field_name);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_by_name(
+ struct bt_ctf_field_type *ft,
+ const char *field_name)
+{
+ return bt_ctf_object_get_ref(bt_ctf_field_type_common_variant_borrow_field_type_by_name(
+ (void *) ft, field_name));
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
+ struct bt_ctf_field_type *ft,
+ struct bt_ctf_field *tag_field)
+{
+ int ret;
+ int64_t choice_index;
+ struct bt_ctf_field *container;
+ struct bt_ctf_field_type_common_variant *var_ft = (void *) ft;
+ struct bt_ctf_field_type *ret_ft = NULL;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+ "Field type");
+ BT_CTF_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_ctf_field_common *) tag_field,
+ BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
+ BT_CTF_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);
+ BT_ASSERT(container);
+
+ if (var_ft->tag_ft->container_ft->is_signed) {
+ int64_t val;
+
+ ret = bt_ctf_field_integer_signed_get_value(container,
+ &val);
+ BT_ASSERT(ret == 0);
+ choice_index = bt_ctf_field_type_common_variant_find_choice_index(
+ (void *) ft, (uint64_t) val, true);
+ } else {
+ uint64_t val;
+
+ ret = bt_ctf_field_integer_unsigned_get_value(container,
+ &val);
+ BT_ASSERT(ret == 0);
+ choice_index = bt_ctf_field_type_common_variant_find_choice_index(
+ (void *) ft, val, false);
+ }
+
+ if (choice_index < 0) {
+ BT_LOGW("Cannot find variant field type's field: "
+ "var-ft-addr=%p, tag-field-addr=%p", ft, tag_field);
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_variant_get_field_by_index(ft, NULL,
+ &ret_ft, choice_index);
+ BT_ASSERT(ret == 0);
+
+end:
+ return ret_ft;
+}
+
+int64_t bt_ctf_field_type_variant_get_field_count(struct bt_ctf_field_type *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_ctf_field_type_common_variant_borrow_field_by_index(
+ (void *) ft, field_name, (void *) field_type, index);
+
+ if (ret == 0 && field_type) {
+ bt_ctf_object_get_ref(*field_type);
+ }
+
+ return ret;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_array_create(
+ struct bt_ctf_field_type *element_ft, unsigned int length)
+{
+ 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);
+
+ if (!element_ft) {
+ BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+ goto error;
+ }
+
+ if (length == 0) {
+ BT_LOGW_STR("Invalid parameter: length is zero.");
+ goto error;
+ }
+
+ array = g_new0(struct bt_ctf_field_type_common_array, 1);
+ if (!array) {
+ BT_LOGE_STR("Failed to allocate one array field type.");
+ goto error;
+ }
+
+ bt_ctf_field_type_common_array_initialize(BT_CTF_TO_COMMON(array),
+ (void *) element_ft, length,
+ 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;
+ BT_LOGD("Created CTF writer array field type object: addr=%p, "
+ "element-ft-addr=%p, length=%u",
+ array, element_ft, length);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(array);
+
+end:
+ return (void *) array;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
+ struct bt_ctf_field_type *ft)
+{
+ return bt_ctf_object_get_ref(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_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_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);
+
+ if (!element_ft) {
+ BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+ goto error;
+ }
+
+ 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_ctf_field_type_common_sequence, 1);
+ if (!sequence) {
+ BT_LOGE_STR("Failed to allocate one sequence field type.");
+ goto error;
+ }
+
+ bt_ctf_field_type_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
+ (void *) element_ft, length_field_name,
+ 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;
+ BT_LOGD("Created CTF writer sequence field type object: addr=%p, "
+ "element-ft-addr=%p, length-field-name=\"%s\"",
+ sequence, element_ft, length_field_name);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(sequence);
+
+end:
+ return (void *) sequence;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
+ struct bt_ctf_field_type *ft)
+{
+ return bt_ctf_object_get_ref(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_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_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.");
+
+ if (!string) {
+ BT_LOGE_STR("Failed to allocate one string field type.");
+ return NULL;
+ }
+
+ 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;
+ BT_LOGD("Created CTF writer string field type object: addr=%p", string);
+ return (void *) string;
+}
+
+enum bt_ctf_string_encoding bt_ctf_field_type_string_get_encoding(
+ struct bt_ctf_field_type *ft)
+{
+ return (int) bt_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_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_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_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_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_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_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_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_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);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer integer field type.");
+ goto end;
+ }
+
+ copy_ft->mapped_clock_class = bt_ctf_object_get_ref(int_ft->mapped_clock_class);
+ copy_ft->user_byte_order = int_ft->user_byte_order;
+ copy_ft->is_signed = int_ft->is_signed;
+ copy_ft->size = int_ft->size;
+ copy_ft->base = int_ft->base;
+ copy_ft->encoding = int_ft->encoding;
+ BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
+ struct bt_ctf_field_type *ft)
+{
+ size_t i;
+ struct bt_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_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;
+ }
+
+ copy_ft = (void *) bt_ctf_field_type_enumeration_create(
+ (void *) container_copy_ft);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
+ goto end;
+ }
+
+ /* Copy all enumaration entries */
+ for (i = 0; i < enum_ft->entries->len; i++) {
+ struct bt_ctf_enumeration_mapping *mapping = g_ptr_array_index(
+ enum_ft->entries, i);
+ 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.");
+ goto error;
+ }
+
+ *copy_mapping = *mapping;
+ g_ptr_array_add(copy_ft->entries, copy_mapping);
+ }
+
+ BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_ctf_object_put_ref(container_copy_ft);
+ return (void *) copy_ft;
+
+error:
+ bt_ctf_object_put_ref(container_copy_ft);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
+ return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
+ struct bt_ctf_field_type *ft)
+{
+ struct bt_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();
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
+ goto end;
+ }
+
+ copy_ft->user_byte_order = flt_ft->user_byte_order;
+ copy_ft->exp_dig = flt_ft->exp_dig;
+ copy_ft->mant_dig = flt_ft->mant_dig;
+ BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
+ struct bt_ctf_field_type *ft)
+{
+ int64_t i;
+ GHashTableIter iter;
+ gpointer key, value;
+ struct bt_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();
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer structure field type.");
+ goto end;
+ }
+
+ /* Copy field_name_to_index */
+ g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ g_hash_table_insert(copy_ft->field_name_to_index,
+ key, value);
+ }
+
+ g_array_set_size(copy_ft->fields, struct_ft->fields->len);
+
+ for (i = 0; i < struct_ft->fields->len; i++) {
+ struct bt_ctf_field_type_common_structure_field *entry, *copy_entry;
+ struct bt_ctf_field_type_common *field_ft_copy;
+
+ entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft, i);
+ 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 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+
+ field_ft_copy = (void *) bt_ctf_field_type_copy(
+ (void *) entry->type);
+ if (!field_ft_copy) {
+ BT_LOGE("Cannot copy CTF writer structure field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+ goto error;
+ }
+
+ copy_entry->name = entry->name;
+ copy_entry->type = field_ft_copy;
+ }
+
+ BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
+ return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
+ struct bt_ctf_field_type *ft)
+{
+ int64_t i;
+ GHashTableIter iter;
+ gpointer key, value;
+ struct bt_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_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;
+ }
+ }
+
+ copy_ft = (void *) bt_ctf_field_type_variant_create(
+ (void *) tag_ft_copy,
+ var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer variant field type.");
+ goto end;
+ }
+
+ /* Copy field_name_to_index */
+ g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ g_hash_table_insert(copy_ft->choice_name_to_index,
+ key, value);
+ }
+
+ g_array_set_size(copy_ft->choices, var_ft->choices->len);
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ 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_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 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+
+ field_ft_copy = (void *) bt_ctf_field_type_copy(
+ (void *) entry->type);
+ if (!field_ft_copy) {
+ BT_LOGE("Cannot copy CTF writer variant field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+ g_free(copy_entry);
+ goto error;
+ }
+
+ copy_entry->name = entry->name;
+ copy_entry->type = field_ft_copy;
+
+ /* Copy ranges */
+ copy_entry->ranges = g_array_new(FALSE, TRUE,
+ 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);
+
+ for (range_i = 0; range_i < entry->ranges->len; range_i++) {
+ copy_entry->ranges[range_i] = entry->ranges[range_i];
+ }
+ }
+
+ 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_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.");
+ goto error;
+ }
+ }
+
+ copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
+ BT_LOGD("Copied CTF writer variant field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_ctf_object_put_ref(tag_ft_copy);
+ return (void *) copy_ft;
+
+error:
+ bt_ctf_object_put_ref(tag_ft_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
+ return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
+ struct bt_ctf_field_type *ft)
+{
+ struct bt_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_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;
+ }
+
+ copy_ft = (void *) bt_ctf_field_type_array_create(
+ (void *) container_ft_copy, array_ft->length);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer array field type.");
+ goto end;
+ }
+
+ BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_ctf_object_put_ref(container_ft_copy);
+ return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
+ struct bt_ctf_field_type *ft)
+{
+ struct bt_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_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;
+ }
+
+ copy_ft = (void *) bt_ctf_field_type_sequence_create(
+ (void *) container_ft_copy,
+ seq_ft->length_field_name->len ?
+ seq_ft->length_field_name->str : NULL);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer sequence field type.");
+ goto end;
+ }
+
+ if (seq_ft->length_field_path) {
+ BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
+ copy_ft->length_field_path = bt_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.");
+ goto error;
+ }
+ }
+
+ BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_ctf_object_put_ref(container_ft_copy);
+ return (void *) copy_ft;
+error:
+ bt_ctf_object_put_ref(container_ft_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
+ return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_string_copy(struct bt_ctf_field_type *ft)
+{
+ 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();
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create CTF writer string field type.");
+ goto end;
+ }
+
+ copy_ft->encoding = string_ft->encoding;
+ BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/object-pool-internal.h>
+#include <babeltrace2/ctf-writer/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_ctf_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_ctf_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_ctf_object_pool_create_object(pool);
+ if (!field_wrapper) {
+ BT_LOGE("Cannot allocate one field wrapper");
+ 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;
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-FIELDS"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/align-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compat/fcntl-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/ctfser-internal.h>
+#include <float.h>
+#include <inttypes.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#define BT_CTF_ASSERT_PRE_CTF_FIELD_IS_INT_OR_ENUM(_field, _name) \
+ BT_CTF_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_CTF_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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_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_CTF_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_CTF_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)
+{
+ int64_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_CTF_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_ctf_field_common_generic_is_set,
+ .reset = bt_ctf_field_common_generic_reset,
+};
+
+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_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_ctf_field_common *field, bool is_frozen);
+
+static
+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_ctf_field_common *field);
+
+static
+void bt_ctf_field_enumeration_reset_recursive(struct bt_ctf_field_common *field);
+
+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,
+ .is_set = bt_ctf_field_enumeration_is_set_recursive,
+ .reset = bt_ctf_field_enumeration_reset_recursive,
+};
+
+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_ctf_field_common_generic_is_set,
+ .reset = bt_ctf_field_common_generic_reset,
+};
+
+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_ctf_field_common_structure_is_set_recursive,
+ .reset = bt_ctf_field_common_structure_reset_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_ctf_field_common_sequence_is_set_recursive,
+ .reset = bt_ctf_field_common_sequence_reset_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_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_ctf_field_common *field,
+ bool is_frozen);
+
+static
+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_ctf_field_common *field);
+
+static
+void bt_ctf_field_variant_reset_recursive(struct bt_ctf_field_common *field);
+
+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,
+ .is_set = bt_ctf_field_variant_is_set_recursive,
+ .reset = bt_ctf_field_variant_reset_recursive,
+};
+
+static
+struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_enumeration_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_floating_point_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_structure_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *(* const field_create_funcs[])(struct bt_ctf_field_type *) = {
+ [BT_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_ctf_field_common *, struct bt_ctfser *,
+ 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_ctf_field_common_integer_finalize((void *) field);
+ g_free(field);
+}
+
+static
+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_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_CTF_FROM_COMMON(field);
+
+ BT_LOGD("Destroying CTF writer enumeration field object: addr=%p",
+ field);
+ BT_LOGD_STR("Putting container field.");
+ bt_ctf_object_put_ref(enumeration->container);
+ bt_ctf_field_common_finalize((void *) field);
+ g_free(field);
+}
+
+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_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_CTF_FROM_COMMON(field);
+
+ BT_LOGD("Destroying CTF writer variant field object: addr=%p", field);
+ BT_LOGD_STR("Putting tag field.");
+ bt_ctf_object_put_ref(variant->tag);
+ bt_ctf_field_common_variant_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+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_ctf_field_common_array_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+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_ctf_field_common_sequence_finalize_recursive((void *) field);
+ g_free(field);
+}
+
+static
+void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
+{
+ BT_LOGD("Destroying CTF writer string field object: addr=%p", field);
+ bt_ctf_field_common_string_finalize((void *) field);
+ g_free(field);
+}
+
+BT_HIDDEN
+int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ struct bt_ctf_field_common *field_common = (void *) field;
+ bt_ctf_field_serialize_recursive_func serialize_func;
+
+ BT_ASSERT(ctfser);
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT(field_common->spec.writer.serialize_func);
+ serialize_func = field_common->spec.writer.serialize_func;
+ return serialize_func(field_common, ctfser,
+ native_byte_order);
+}
+
+static
+int bt_ctf_field_integer_serialize(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int ret;
+ 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;
+
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Integer field");
+ BT_LOGV("Serializing CTF writer integer field: addr=%p, native-bo=%s",
+ field,
+ bt_ctf_byte_order_string(native_byte_order));
+ byte_order = int_type->user_byte_order;
+ if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+ byte_order = native_byte_order;
+ }
+
+ if (int_type->is_signed) {
+ ret = bt_ctfser_write_signed_int(ctfser,
+ int_field->payload.signd, int_type->common.alignment,
+ int_type->size,
+ byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+ LITTLE_ENDIAN : BIG_ENDIAN);
+ } else {
+ ret = bt_ctfser_write_unsigned_int(ctfser,
+ int_field->payload.unsignd, int_type->common.alignment,
+ int_type->size,
+ byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+ LITTLE_ENDIAN : BIG_ENDIAN);
+ }
+
+ if (unlikely(ret)) {
+ BT_LOGE("Cannot serialize integer field: ret=%d", ret);
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_enumeration_serialize_recursive(
+ struct bt_ctf_field_common *field, struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ BT_LOGV("Serializing enumeration field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string(native_byte_order));
+ BT_LOGV_STR("Serializing enumeration field's payload field.");
+ return bt_ctf_field_serialize_recursive(
+ (void *) enumeration->container, ctfser, native_byte_order);
+}
+
+static
+int bt_ctf_field_floating_point_serialize(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int ret = -1;
+ 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;
+
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field");
+ BT_LOGV("Serializing floating point number field: "
+ "addr=%p, native-bo=%s", field,
+ bt_ctf_byte_order_string(native_byte_order));
+
+ byte_order = flt_type->user_byte_order;
+ if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+ byte_order = native_byte_order;
+ }
+
+ if (flt_type->mant_dig == FLT_MANT_DIG) {
+ ret = bt_ctfser_write_float32(ctfser, flt_field->payload,
+ flt_type->common.alignment,
+ byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+ LITTLE_ENDIAN : BIG_ENDIAN);
+ } else if (flt_type->mant_dig == DBL_MANT_DIG) {
+ ret = bt_ctfser_write_float64(ctfser, flt_field->payload,
+ flt_type->common.alignment,
+ byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+ LITTLE_ENDIAN : BIG_ENDIAN);
+ } else {
+ abort();
+ }
+
+ if (unlikely(ret)) {
+ BT_LOGE("Cannot serialize floating point number field: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int64_t i;
+ int ret;
+ struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+ BT_LOGV("Serializing structure field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string(native_byte_order));
+ ret = bt_ctfser_align_offset_in_current_packet(ctfser,
+ field->type->alignment);
+ if (unlikely(ret)) {
+ BT_LOGE("Cannot align offset before serializing structure field: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ for (i = 0; i < structure->fields->len; i++) {
+ struct bt_ctf_field_common *member = g_ptr_array_index(
+ structure->fields, i);
+ const char *field_name = NULL;
+
+ BT_LOGV("Serializing structure field's field: ser-offset=%" PRIu64 ", "
+ "field-addr=%p, index=%" PRIu64,
+ bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+ member, i);
+
+ if (unlikely(!member)) {
+ 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: "
+ "struct-field-addr=%p, "
+ "field-name=\"%s\", index=%" PRId64,
+ field, field_name, i);
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_serialize_recursive((void *) member, ctfser,
+ native_byte_order);
+ if (unlikely(ret)) {
+ 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: "
+ "struct-field-addr=%p, field-addr=%p, "
+ "field-name=\"%s\", index=%" PRId64,
+ field->type, member, field_name, i);
+ break;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_variant_serialize_recursive(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+
+ BT_LOGV("Serializing variant field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string(native_byte_order));
+ BT_LOGV_STR("Serializing variant field's payload field.");
+ return bt_ctf_field_serialize_recursive(
+ (void *) variant->current_field, ctfser, native_byte_order);
+}
+
+static
+int bt_ctf_field_array_serialize_recursive(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int64_t i;
+ int ret = 0;
+ struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+ BT_LOGV("Serializing array field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string(native_byte_order));
+
+ for (i = 0; i < array->elements->len; i++) {
+ struct bt_ctf_field_common *elem_field =
+ g_ptr_array_index(array->elements, i);
+
+ BT_LOGV("Serializing array field's element field: "
+ "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
+ bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+ elem_field, i);
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) elem_field, ctfser, native_byte_order);
+ if (unlikely(ret)) {
+ BT_LOGW("Cannot serialize array field's element field: "
+ "array-field-addr=%p, field-addr=%p, "
+ "index=%" PRId64, field, elem_field, i);
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_sequence_serialize_recursive(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int64_t i;
+ int ret = 0;
+ struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+ BT_LOGV("Serializing sequence field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string(native_byte_order));
+
+ for (i = 0; i < sequence->elements->len; i++) {
+ struct bt_ctf_field_common *elem_field =
+ g_ptr_array_index(sequence->elements, i);
+
+ BT_LOGV("Serializing sequence field's element field: "
+ "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
+ bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+ elem_field, i);
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) elem_field, ctfser, native_byte_order);
+ if (unlikely(ret)) {
+ BT_LOGW("Cannot serialize sequence field's element field: "
+ "sequence-field-addr=%p, field-addr=%p, "
+ "index=%" PRId64, field, elem_field, i);
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+int bt_ctf_field_string_serialize(struct bt_ctf_field_common *field,
+ struct bt_ctfser *ctfser,
+ enum bt_ctf_byte_order native_byte_order)
+{
+ int ret;
+ struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
+
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field");
+ BT_LOGV("Serializing string field: addr=%p, native-bo=%s",
+ field, bt_ctf_byte_order_string((int) native_byte_order));
+ ret = bt_ctfser_write_string(ctfser, (const char *) string->buf->data);
+ if (unlikely(ret)) {
+ BT_LOGE("Cannot serialize string field: ret=%d", ret);
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
+{
+ struct bt_ctf_field *field = NULL;
+ enum bt_ctf_field_type_id type_id;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(type, "Field type");
+ BT_ASSERT(field_type_common_has_known_id((void *) type));
+ BT_CTF_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_ctf_field_type_common_freeze((void *) type);
+
+end:
+ return field;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
+{
+ return bt_ctf_object_get_ref(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_ctf_field_common *field_common = (void *) field;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Field");
+ return (int) field_common->type->id;
+}
+
+int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
+ struct bt_ctf_field *length_field)
+{
+ int ret;
+ struct bt_ctf_field_common *common_length_field = (void *) length_field;
+ uint64_t length;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(length_field, "Length field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((void *) length_field, "Length field");
+ BT_CTF_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_CTF_FIELD_TYPE_ID_ENUM) {
+ struct bt_ctf_field_enumeration *enumeration = (void *)
+ length_field;
+
+ length_field = (void *) enumeration->container;
+ }
+
+ ret = bt_ctf_field_integer_unsigned_get_value(length_field, &length);
+ BT_ASSERT(ret == 0);
+ 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_ctf_object_get_ref(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_ctf_object_get_ref(bt_ctf_field_common_structure_borrow_field_by_name(
+ (void *) field, name));
+}
+
+struct bt_ctf_field *bt_ctf_field_array_get_field(
+ struct bt_ctf_field *field, uint64_t index)
+{
+ return bt_ctf_object_get_ref(
+ 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_ctf_object_get_ref(
+ 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,
+ struct bt_ctf_field *tag_field)
+{
+ struct bt_ctf_field_variant *variant_field = (void *) field;
+ struct bt_ctf_field_enumeration *enum_field = (void *) tag_field;
+ 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;
+ int ret;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Variant field");
+ BT_CTF_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((void *) tag_field, "Tag field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_ctf_field_common *) tag_field,
+ BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+ (struct bt_ctf_field_common *) field,
+ BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_CTF_ASSERT_PRE(
+ 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_CTF_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_CTF_FROM_COMMON(enum_field->common.type);
+ is_signed = tag_ft->container_ft->is_signed;
+
+ if (is_signed) {
+ int64_t tag_ival;
+
+ ret = bt_ctf_field_integer_signed_get_value(
+ (void *) enum_field->container, &tag_ival);
+ tag_uval = (uint64_t) tag_ival;
+ } else {
+ ret = bt_ctf_field_integer_unsigned_get_value(
+ (void *) enum_field->container, &tag_uval);
+ }
+
+ BT_ASSERT(ret == 0);
+ ret = bt_ctf_field_common_variant_set_tag((void *) field, tag_uval,
+ is_signed);
+ if (ret) {
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(variant_field->tag);
+ variant_field->tag = bt_ctf_object_get_ref(tag_field);
+ current_field = bt_ctf_field_variant_get_current_field(field);
+ BT_ASSERT(current_field);
+
+end:
+ return current_field;
+}
+
+struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
+ struct bt_ctf_field *variant_field)
+{
+ return bt_ctf_object_get_ref(bt_ctf_field_common_variant_borrow_current_field(
+ (void *) variant_field));
+}
+
+BT_HIDDEN
+struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
+ struct bt_ctf_field *field)
+{
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Enumeration field");
+ BT_CTF_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;
+}
+
+struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
+ struct bt_ctf_field *field)
+{
+ return bt_ctf_object_get_ref(bt_ctf_field_enumeration_borrow_container(field));
+}
+
+int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field,
+ int64_t *value)
+{
+ struct bt_ctf_field_common_integer *integer = (void *) field;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(BT_CTF_TO_COMMON(integer), "Integer field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+ BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
+ BT_CTF_ASSERT_PRE(bt_ctf_field_type_common_integer_is_signed(
+ integer->common.type),
+ "Field's type is unsigned: field-addr=%p", field);
+ *value = integer->payload.signd;
+ return 0;
+}
+
+int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field,
+ int64_t value)
+{
+ int ret = 0;
+ struct bt_ctf_field_common_integer *integer = (void *) field;
+ struct bt_ctf_field_type_common_integer *integer_type;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(BT_CTF_TO_COMMON(integer), "Integer field");
+ BT_CTF_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_CTF_ASSERT_PRE(
+ bt_ctf_field_type_common_integer_is_signed(integer->common.type),
+ "Field's type is unsigned: field-addr=%p", field);
+ BT_CTF_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
+ "Value is out of bounds: value=%" PRId64 ", field-addr=%p",
+ value, field);
+ integer->payload.signd = value;
+ 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_ctf_field_common_integer *integer = (void *) field;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(BT_CTF_TO_COMMON(integer), "Integer field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+ BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
+ BT_CTF_ASSERT_PRE(
+ !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;
+}
+
+int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field,
+ uint64_t value)
+{
+ struct bt_ctf_field_common_integer *integer = (void *) field;
+ struct bt_ctf_field_type_common_integer *integer_type;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Integer field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(BT_CTF_TO_COMMON(integer), "Integer field");
+ BT_CTF_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_CTF_ASSERT_PRE(
+ !bt_ctf_field_type_common_integer_is_signed(integer->common.type),
+ "Field's type is signed: field-addr=%p", field);
+ BT_CTF_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
+ "Value is out of bounds: value=%" PRIu64 ", field-addr=%p",
+ value, field);
+ integer->payload.unsignd = value;
+ 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_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_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_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_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_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_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_ctf_field_common_copy((void *) field);
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type)
+{
+ 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_ctf_field_common_initialize(BT_CTF_TO_COMMON(integer), (void *) type,
+ true,
+ (bt_ctf_object_release_func) bt_ctf_field_integer_destroy,
+ &bt_ctf_field_integer_methods);
+ integer->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_integer_serialize;
+ BT_LOGD("Created CTF writer integer field object: addr=%p, ft-addr=%p",
+ integer, type);
+ } else {
+ BT_LOGE_STR("Failed to allocate one integer field.");
+ }
+
+ return (void *) integer;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_enumeration_create(
+ struct bt_ctf_field_type *type)
+{
+ struct bt_ctf_field_type_common_enumeration *enum_ft = (void *) type;
+ struct bt_ctf_field_enumeration *enumeration = g_new0(
+ struct bt_ctf_field_enumeration, 1);
+
+ BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type);
+
+ if (!enumeration) {
+ BT_LOGE_STR("Failed to allocate one enumeration field.");
+ goto end;
+ }
+
+ bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(enumeration),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_enumeration_destroy_recursive,
+ &bt_ctf_field_enumeration_methods);
+ enumeration->container = (void *) bt_ctf_field_create(
+ BT_CTF_FROM_COMMON(enum_ft->container_ft));
+ if (!enumeration->container) {
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(enumeration);
+ goto end;
+ }
+
+ enumeration->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func)
+ bt_ctf_field_enumeration_serialize_recursive;
+ BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
+ enumeration, type);
+
+end:
+ return (void *) enumeration;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_floating_point_create(
+ struct bt_ctf_field_type *type)
+{
+ 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_ctf_field_common_floating_point, 1);
+
+ if (floating_point) {
+ bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(floating_point),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_floating_point_destroy,
+ &bt_ctf_field_floating_point_methods);
+ floating_point->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_floating_point_serialize;
+ BT_LOGD("Created CTF writer floating point number field object: addr=%p, ft-addr=%p",
+ floating_point, type);
+ } else {
+ BT_LOGE_STR("Failed to allocate one floating point number field.");
+ }
+
+ return (void *) floating_point;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_structure_create(
+ struct bt_ctf_field_type *type)
+{
+ struct bt_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);
+
+ if (!structure) {
+ BT_LOGE_STR("Failed to allocate one structure field.");
+ goto end;
+ }
+
+ iret = bt_ctf_field_common_structure_initialize(BT_CTF_TO_COMMON(structure),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_structure_destroy_recursive,
+ &bt_ctf_field_structure_methods,
+ (bt_ctf_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ structure->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive;
+ if (iret) {
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(structure);
+ goto end;
+ }
+
+ BT_LOGD("Created CTF writer structure field object: addr=%p, ft-addr=%p",
+ structure, type);
+
+end:
+ return (void *) structure;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
+{
+ struct bt_ctf_field_type_common_variant *var_ft = (void *) type;
+ struct bt_ctf_field_variant *variant = g_new0(
+ struct bt_ctf_field_variant, 1);
+
+ BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type);
+
+ if (!variant) {
+ BT_LOGE_STR("Failed to allocate one variant field.");
+ goto end;
+ }
+
+ bt_ctf_field_common_variant_initialize(BT_CTF_TO_COMMON(BT_CTF_TO_COMMON(variant)),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_variant_destroy_recursive,
+ &bt_ctf_field_variant_methods,
+ (bt_ctf_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ variant->tag = (void *) bt_ctf_field_create(
+ 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",
+ variant, type);
+
+end:
+ return (void *) variant;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
+{
+ 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);
+ BT_ASSERT(type);
+
+ if (!array) {
+ BT_LOGE_STR("Failed to allocate one array field.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_common_array_initialize(BT_CTF_TO_COMMON(array),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_array_destroy_recursive,
+ &bt_ctf_field_array_methods,
+ (bt_ctf_field_common_create_func) bt_ctf_field_create,
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ array->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive;
+ if (ret) {
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(array);
+ goto end;
+ }
+
+ BT_LOGD("Created CTF writer array field object: addr=%p, ft-addr=%p",
+ array, type);
+
+end:
+ return (void *) array;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type)
+{
+ struct bt_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_ctf_field_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_sequence_destroy_recursive,
+ &bt_ctf_field_sequence_methods,
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ sequence->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_sequence_serialize_recursive;
+ BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p",
+ sequence, type);
+ } else {
+ BT_LOGE_STR("Failed to allocate one sequence field.");
+ }
+
+ return (void *) sequence;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
+{
+ struct bt_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_ctf_field_common_string_initialize(BT_CTF_TO_COMMON(string),
+ (void *) type,
+ true, (bt_ctf_object_release_func)
+ bt_ctf_field_string_destroy,
+ &bt_ctf_field_string_methods);
+ string->common.spec.writer.serialize_func =
+ (bt_ctf_field_serialize_recursive_func) bt_ctf_field_string_serialize;
+ BT_LOGD("Created CTF writer string field object: addr=%p, ft-addr=%p",
+ string, type);
+ } else {
+ BT_LOGE_STR("Failed to allocate one string field.");
+ }
+
+ return (void *) string;
+}
+
+static
+void bt_ctf_field_enumeration_set_is_frozen_recursive(
+ struct bt_ctf_field_common *field, bool is_frozen)
+{
+ struct bt_ctf_field_enumeration *enumeration = (void *) field;
+
+ if (enumeration->container) {
+ bt_ctf_field_common_set_is_frozen_recursive(
+ (void *) enumeration->container, is_frozen);
+ }
+
+ bt_ctf_field_common_generic_set_is_frozen((void *) field, is_frozen);
+}
+
+static
+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_ctf_field_common_validate_recursive(
+ (void *) enumeration->container);
+ }
+
+ return ret;
+}
+
+static
+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_ctf_field_common_is_set_recursive(
+ (void *) enumeration->container);
+ }
+
+ return is_set;
+}
+
+static
+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_ctf_field_common_reset_recursive(
+ (void *) enumeration->container);
+ }
+
+ bt_ctf_field_common_generic_reset((void *) field);
+}
+
+static
+void bt_ctf_field_variant_set_is_frozen_recursive(
+ struct bt_ctf_field_common *field, bool is_frozen)
+{
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ bt_ctf_field_common_set_is_frozen_recursive(
+ (void *) variant->tag, is_frozen);
+ }
+
+ bt_ctf_field_common_variant_set_is_frozen_recursive((void *) field,
+ is_frozen);
+}
+
+static
+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_ctf_field_common_validate_recursive(
+ (void *) variant->tag);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ 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_ctf_field_common *field)
+{
+ bt_bool is_set;
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ is_set = bt_ctf_field_common_is_set_recursive(
+ (void *) variant->tag);
+ if (is_set) {
+ goto end;
+ }
+ }
+
+ 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_ctf_field_common *field)
+{
+ struct bt_ctf_field_variant *variant = (void *) field;
+
+ if (variant->tag) {
+ bt_ctf_field_common_reset_recursive(
+ (void *) variant->tag);
+ }
+
+ bt_ctf_field_common_variant_reset_recursive((void *) field);
+}
+
+BT_CTF_ASSERT_PRE_FUNC
+static inline bool field_to_set_has_expected_type(
+ struct bt_ctf_field_common *struct_field,
+ const char *name, struct bt_ctf_field_common *value)
+{
+ bool ret = true;
+ struct bt_ctf_field_type_common *expected_field_type = NULL;
+
+ expected_field_type =
+ bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+ struct_field->type, name);
+
+ if (bt_ctf_field_type_common_compare(expected_field_type, value->type)) {
+ BT_CTF_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
+ "value-ft-addr=%p, expected-ft-addr=%p", value->type,
+ expected_field_type);
+ ret = false;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
+ const char *name, struct bt_ctf_field *value)
+{
+ int ret = 0;
+ GQuark field_quark;
+ 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_ctf_field_type_common_structure *structure_ft;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Parent field");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Field name");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(common_field,
+ BT_CTF_FIELD_TYPE_ID_STRUCT, "Parent field");
+ BT_CTF_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_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,
+ (gpointer *) &index)) {
+ BT_LOGV("Invalid parameter: no such field in structure field's type: "
+ "struct-field-addr=%p, struct-ft-addr=%p, "
+ "field-ft-addr=%p, name=\"%s\"",
+ field, common_field->type, common_value->type, name);
+ ret = -1;
+ goto end;
+ }
+ bt_ctf_object_get_ref(value);
+ BT_CTF_OBJECT_MOVE_REF(structure->fields->pdata[index], value);
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * functor.c
+ *
+ * Babeltrace CTF Writer
+ *
+ * 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 <glib.h>
+#include <babeltrace2/ctf-writer/functor-internal.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+
+BT_HIDDEN
+void value_exists(gpointer element, gpointer search_query)
+{
+ if (element == ((struct bt_ctf_search_query *)search_query)->value) {
+ ((struct bt_ctf_search_query *)search_query)->found = 1;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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_OUTPUT_LEVEL bt_lib_ctf_writer_log_level
+#include "logging.h"
+
+BT_LOG_INIT_LOG_LEVEL(bt_lib_ctf_writer_log_level,
+ "BABELTRACE_CTF_WRITER_LOG_LEVEL");
--- /dev/null
+#ifndef BABELTRACE_CTF_WRITER_LOGGING_H
+#define BABELTRACE_CTF_WRITER_LOGGING_H
+
+/*
+ * Copyright (c) 2017 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_OUTPUT_LEVEL bt_lib_ctf_writer_log_level
+#include <babeltrace2/logging-internal.h>
+
+BT_LOG_LEVEL_EXTERN_SYMBOL(bt_lib_ctf_writer_log_level);
+
+#endif /* BABELTRACE_CTF_WRITER_LOGGING_H */
--- /dev/null
+/*
+ * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 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 "OBJECT-POOL"
+#include "logging.h"
+
+#include <stdint.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/ctf-writer/object-pool-internal.h>
+
+int bt_ctf_object_pool_initialize(struct bt_ctf_object_pool *pool,
+ bt_ctf_object_pool_new_object_func new_object_func,
+ bt_ctf_object_pool_destroy_object_func destroy_object_func,
+ void *data)
+{
+ int ret = 0;
+
+ BT_ASSERT(new_object_func);
+ BT_ASSERT(destroy_object_func);
+ BT_LOGD("Initializing object pool: addr=%p, data-addr=%p",
+ pool, data);
+ pool->objects = g_ptr_array_new();
+ if (!pool->objects) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ goto error;
+ }
+
+ pool->funcs.new_object = new_object_func;
+ pool->funcs.destroy_object = destroy_object_func;
+ pool->data = data;
+ pool->size = 0;
+ BT_LOGD("Initialized object pool.");
+ goto end;
+
+error:
+ if (pool) {
+ bt_ctf_object_pool_finalize(pool);
+ }
+
+ ret = -1;
+
+end:
+ return ret;
+}
+
+void bt_ctf_object_pool_finalize(struct bt_ctf_object_pool *pool)
+{
+ uint64_t i;
+
+ BT_ASSERT(pool);
+ BT_LOGD("Finalizing object pool.");
+
+ if (pool->objects) {
+ for (i = 0; i < pool->size; i++) {
+ void *obj = pool->objects->pdata[i];
+
+ if (obj) {
+ pool->funcs.destroy_object(obj, pool->data);
+ }
+ }
+
+ g_ptr_array_free(pool->objects, TRUE);
+ pool->objects = NULL;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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 <babeltrace2/ctf-writer/object-internal.h>
+
+void *bt_ctf_object_get_ref(void *obj)
+{
+ if (unlikely(!obj)) {
+ goto end;
+ }
+
+ bt_ctf_object_get_no_null_check(obj);
+
+end:
+ return obj;
+}
+
+void bt_ctf_object_put_ref(void *obj)
+{
+ if (unlikely(!obj)) {
+ return;
+ }
+
+ bt_ctf_object_put_no_null_check(obj);
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/babeltrace-internal.h>
+#include <babeltrace2/ctf-writer/field-path-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <babeltrace2/ctf-writer/resolve-internal.h>
+#include <babeltrace2/ctf-writer/stream-class.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/ctf-writer/values-internal.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_ctf_private_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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(child_type);
+ BT_CTF_OBJECT_MOVE_REF(type, child_type);
+ }
+
+end:
+ bt_ctf_object_put_ref(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(child_type);
+ BT_CTF_OBJECT_MOVE_REF(type, child_type);
+ }
+
+ return type;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(target_field_path);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_private_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;
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-STREAM-CLASS"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/align-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/event-internal.h>
+#include <babeltrace2/ctf-writer/event.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/trace.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/validation-internal.h>
+#include <babeltrace2/ctf-writer/visitor-internal.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object.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_ctf_object_release_func release_func)
+{
+ BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
+
+ bt_ctf_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_ctf_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_ctf_object_put_ref(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_ctf_object_put_ref(stream_class->event_header_field_type);
+ BT_LOGD_STR("Putting packet context field type.");
+ bt_ctf_object_put_ref(stream_class->packet_context_field_type);
+ BT_LOGD_STR("Putting event context field type.");
+ bt_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(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 = bt_ctf_visitor_helper(&obj, get_event_class_count,
+ get_event_class,
+ visit_event_class, visitor, data);
+ BT_LOGV("bt_ctf_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)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *event_header_type =
+ bt_ctf_field_type_structure_create();
+ struct bt_ctf_field_type *_uint32_t =
+ get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
+ struct bt_ctf_field_type *_uint64_t =
+ get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+
+ if (!event_header_type) {
+ BT_LOGE_STR("Cannot create empty structure field type.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(event_header_type,
+ _uint32_t, "id");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `id` field to event header field type.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(event_header_type,
+ _uint64_t, "timestamp");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(stream_class->common.event_header_field_type);
+ stream_class->common.event_header_field_type =
+ (void *) event_header_type;
+ event_header_type = NULL;
+
+end:
+ if (ret) {
+ bt_ctf_object_put_ref(event_header_type);
+ }
+
+ bt_ctf_object_put_ref(_uint32_t);
+ bt_ctf_object_put_ref(_uint64_t);
+ return ret;
+}
+
+static
+int init_packet_context(struct bt_ctf_stream_class *stream_class)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *packet_context_type =
+ bt_ctf_field_type_structure_create();
+ struct bt_ctf_field_type *_uint64_t =
+ get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+ struct bt_ctf_field_type *ts_begin_end_uint64_t;
+
+ if (!packet_context_type) {
+ BT_LOGE_STR("Cannot create empty structure field type.");
+ ret = -1;
+ goto end;
+ }
+
+ ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
+ if (!ts_begin_end_uint64_t) {
+ BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
+ ret = -1;
+ goto end;
+ }
+
+ /*
+ * We create a stream packet context as proposed in the CTF
+ * specification.
+ */
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ ts_begin_end_uint64_t, "timestamp_begin");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ ts_begin_end_uint64_t, "timestamp_end");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ _uint64_t, "content_size");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ _uint64_t, "packet_size");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+ _uint64_t, "events_discarded");
+ if (ret) {
+ BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(stream_class->common.packet_context_field_type);
+ stream_class->common.packet_context_field_type =
+ (void *) packet_context_type;
+ packet_context_type = NULL;
+
+end:
+ if (ret) {
+ bt_ctf_object_put_ref(packet_context_type);
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(_uint64_t);
+ bt_ctf_object_put_ref(ts_begin_end_uint64_t);
+ return ret;
+}
+
+static
+void bt_ctf_stream_class_destroy(struct bt_ctf_object *obj)
+{
+ struct bt_ctf_stream_class *stream_class;
+
+ stream_class = (void *) obj;
+ BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class));
+ bt_ctf_object_put_ref(stream_class->clock);
+ g_free(stream_class);
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
+{
+ struct bt_ctf_stream_class *stream_class;
+ int ret;
+
+ BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name);
+ stream_class = g_new0(struct bt_ctf_stream_class, 1);
+ if (!stream_class) {
+ BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
+ goto error;
+ }
+
+ ret = bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class),
+ name, bt_ctf_stream_class_destroy);
+ if (ret) {
+ /* bt_ctf_stream_class_common_initialize() logs errors */
+ goto error;
+ }
+
+ ret = init_event_header(stream_class);
+ if (ret) {
+ BT_LOGE_STR("Cannot initialize stream class's event header field type.");
+ goto error;
+ }
+
+ ret = init_packet_context(stream_class);
+ if (ret) {
+ BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
+ goto error;
+ }
+
+ BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
+ stream_class, name);
+ return stream_class;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class);
+ return stream_class;
+}
+
+static
+int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *parent_ft, const char *field_name)
+{
+ struct bt_ctf_clock_class *mapped_clock_class = NULL;
+ int ret = 0;
+ struct bt_ctf_field_type *ft =
+ bt_ctf_field_type_structure_get_field_type_by_name(parent_ft,
+ field_name);
+
+ BT_ASSERT(stream_class->clock);
+
+ if (!ft) {
+ /* Field does not exist: not an error */
+ goto end;
+ }
+
+ BT_ASSERT(((struct bt_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) {
+ struct bt_ctf_field_type *ft_copy;
+
+ if (!stream_class->clock) {
+ BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", ft-addr=%p",
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), ft);
+ ret = -1;
+ goto end;
+ }
+
+ ft_copy = bt_ctf_field_type_copy(ft);
+ if (!ft_copy) {
+ BT_LOGE("Failed to copy integer field type: ft-addr=%p",
+ ft);
+ }
+
+ ret = bt_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_ctf_field_type_common_structure_replace_field(
+ (void *) parent_ft, field_name, (void *) ft_copy);
+ bt_ctf_object_put_ref(ft_copy);
+ BT_LOGV("Automatically mapped field type to stream class's clock class: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", ft-addr=%p, "
+ "ft-copy-addr=%p",
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
+ }
+
+end:
+ bt_ctf_object_put_ref(ft);
+ bt_ctf_object_put_ref(mapped_clock_class);
+ return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_map_clock_class(
+ struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_field_type *packet_context_type,
+ struct bt_ctf_field_type *event_header_type)
+{
+ int ret = 0;
+
+ BT_ASSERT(stream_class);
+
+ if (!stream_class->clock) {
+ /* No clock class to map to */
+ goto end;
+ }
+
+ if (packet_context_type) {
+ if (try_map_clock_class(stream_class, packet_context_type,
+ "timestamp_begin")) {
+ BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ if (try_map_clock_class(stream_class, packet_context_type,
+ "timestamp_end")) {
+ BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+ }
+
+ if (event_header_type) {
+ if (try_map_clock_class(stream_class, event_header_type,
+ "timestamp")) {
+ BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
+ ret = -1;
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
+ struct bt_ctf_stream_class *stream_class)
+{
+ struct bt_ctf_clock *clock = NULL;
+
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ goto end;
+ }
+
+ if (!stream_class->clock) {
+ BT_LOGV("Stream class has no clock: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ goto end;
+ }
+
+ clock = bt_ctf_object_get_ref(stream_class->clock);
+
+end:
+ return clock;
+}
+
+int bt_ctf_stream_class_set_clock(
+ struct bt_ctf_stream_class *stream_class,
+ struct bt_ctf_clock *clock)
+{
+ int ret = 0;
+
+ if (!stream_class || !clock) {
+ BT_LOGW("Invalid parameter: stream class or clock is NULL: "
+ "stream-class-addr=%p, clock-addr=%p",
+ stream_class, clock);
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->common.frozen) {
+ BT_LOGW("Invalid parameter: stream class is frozen: "
+ "addr=%p, name=\"%s\", id=%" PRId64,
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class));
+ ret = -1;
+ goto end;
+ }
+
+ /* Replace the current clock of this stream class. */
+ bt_ctf_object_put_ref(stream_class->clock);
+ stream_class->clock = bt_ctf_object_get_ref(clock);
+ BT_LOGV("Set stream class's clock: "
+ "addr=%p, name=\"%s\", id=%" PRId64 ", "
+ "clock-addr=%p, clock-name=\"%s\"",
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class),
+ stream_class->clock,
+ bt_ctf_clock_get_name(stream_class->clock));
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
+ struct metadata_context *context)
+{
+ int ret = 0;
+ size_t i;
+ struct bt_ctf_trace *trace;
+ struct bt_ctf_field_type *packet_header_type = NULL;
+
+ BT_LOGD("Serializing stream class's metadata: "
+ "stream-class-addr=%p, stream-class-name=\"%s\", "
+ "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
+ stream_class,
+ bt_ctf_stream_class_get_name(stream_class),
+ bt_ctf_stream_class_get_id(stream_class), context);
+ g_string_assign(context->field_name, "");
+ context->current_indentation_level = 1;
+ if (!stream_class->common.id_set) {
+ BT_LOGW_STR("Stream class's ID is not set.");
+ ret = -1;
+ goto end;
+ }
+
+ g_string_append(context->string, "stream {\n");
+
+ /*
+ * The reference to the trace is only borrowed since the
+ * serialization of the stream class might have been triggered
+ * by the trace's destruction. In such a case, the trace's
+ * reference count would, unexepectedly, go through the sequence
+ * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
+ * and serialization.
+ */
+ trace = BT_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;
+ if (packet_header_type) {
+ struct bt_ctf_field_type *stream_id_type;
+
+ stream_id_type =
+ bt_ctf_field_type_structure_get_field_type_by_name(
+ packet_header_type, "stream_id");
+ if (stream_id_type) {
+ /*
+ * Only set the stream's id if the trace's packet header
+ * contains a stream_id field. This field is only
+ * needed if the trace contains only one stream
+ * class.
+ */
+ g_string_append_printf(context->string,
+ "\tid = %" PRId64 ";\n",
+ stream_class->common.id);
+ }
+ bt_ctf_object_put_ref(stream_id_type);
+ }
+ if (stream_class->common.event_header_field_type) {
+ BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
+ g_string_append(context->string, "\tevent.header := ");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) stream_class->common.event_header_field_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";");
+ }
+
+
+ if (stream_class->common.packet_context_field_type) {
+ BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
+ g_string_append(context->string, "\n\n\tpacket.context := ");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) stream_class->common.packet_context_field_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";");
+ }
+
+ if (stream_class->common.event_context_field_type) {
+ BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
+ g_string_append(context->string, "\n\n\tevent.context := ");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) stream_class->common.event_context_field_type,
+ context);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
+ "ret=%d", ret);
+ goto end;
+ }
+ g_string_append(context->string, ";");
+ }
+
+ g_string_append(context->string, "\n};\n\n");
+
+ for (i = 0; i < stream_class->common.event_classes->len; i++) {
+ struct bt_ctf_event_class *event_class =
+ stream_class->common.event_classes->pdata[i];
+
+ ret = bt_ctf_event_class_serialize(event_class, context);
+ if (ret) {
+ BT_LOGW("Cannot serialize event class's metadata: "
+ "event-class-addr=%p, event-class-name=\"%s\", "
+ "event-class-id=%" PRId64,
+ event_class,
+ bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class));
+ goto end;
+ }
+ }
+
+end:
+ bt_ctf_object_put_ref(packet_header_type);
+ context->current_indentation_level = 0;
+ return ret;
+}
+
+struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
+ struct bt_ctf_stream_class *stream_class)
+{
+ return bt_ctf_object_get_ref(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_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_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_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_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_ctf_object_get_ref(
+ 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_ctf_stream_class_common_set_packet_context_field_type(
+ BT_CTF_TO_COMMON(stream_class), (void *) packet_context_type);
+}
+
+struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_header_type(
+ struct bt_ctf_stream_class *stream_class)
+{
+ return bt_ctf_object_get_ref(
+ 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_ctf_stream_class_common_set_event_header_field_type(
+ BT_CTF_TO_COMMON(stream_class), (void *) event_header_type);
+}
+
+struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_context_type(
+ struct bt_ctf_stream_class *stream_class)
+{
+ return bt_ctf_object_get_ref(
+ 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_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_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_ctf_object_get_ref(
+ 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_ctf_object_get_ref(
+ 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_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);
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-STREAM"
+#include "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/align-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/event-internal.h>
+#include <babeltrace2/ctf-writer/field-types.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/stream-class.h>
+#include <babeltrace2/ctf-writer/stream-internal.h>
+#include <babeltrace2/ctf-writer/stream.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/trace.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/ctfser-internal.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_ctf_object_release_func release_func)
+{
+ int ret = 0;
+ struct bt_ctf_trace_common *trace = NULL;
+
+ bt_ctf_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_ctf_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_ctf_object *obj);
+
+static
+int try_set_structure_field_integer(struct bt_ctf_field *, char *, uint64_t);
+
+static
+int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *field_type = NULL;
+
+ if (!field) {
+ BT_LOGW_STR("Invalid parameter: field is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ field_type = bt_ctf_field_get_type(field);
+ BT_ASSERT(field_type);
+
+ if (bt_ctf_field_type_get_type_id(field_type) !=
+ BT_CTF_FIELD_TYPE_ID_INTEGER) {
+ /* Not an integer and the value is unset, error. */
+ BT_LOGW("Invalid parameter: field's type is not an integer field type: "
+ "field-addr=%p, ft-addr=%p, ft-id=%s",
+ field, field_type,
+ bt_ctf_field_type_id_string((int)
+ bt_ctf_field_type_get_type_id(field_type)));
+ ret = -1;
+ goto end;
+ }
+
+ if (bt_ctf_field_type_integer_is_signed(field_type)) {
+ ret = bt_ctf_field_integer_signed_set_value(field, (int64_t) value);
+ if (ret) {
+ /* Value is out of range, error. */
+ BT_LOGW("Cannot set signed integer field's value: "
+ "addr=%p, value=%" PRId64,
+ field, (int64_t) value);
+ goto end;
+ }
+ } else {
+ ret = bt_ctf_field_integer_unsigned_set_value(field, value);
+ if (ret) {
+ /* Value is out of range, error. */
+ BT_LOGW("Cannot set unsigned integer field's value: "
+ "addr=%p, value=%" PRIu64,
+ field, value);
+ goto end;
+ }
+ }
+end:
+ bt_ctf_object_put_ref(field_type);
+ return ret;
+}
+
+static
+int set_packet_header_magic(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_header, "magic");
+ const uint32_t magic_value = 0xc1fc1fc1;
+
+ BT_ASSERT(stream);
+
+ if (!magic_field) {
+ /* No magic field found. Not an error, skip. */
+ BT_LOGV("No field named `magic` in packet header: skipping: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ ret = bt_ctf_field_integer_unsigned_set_value(magic_field,
+ (uint64_t) magic_value);
+
+ if (ret) {
+ BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ magic_field, (uint64_t) magic_value);
+ } else {
+ BT_LOGV("Set packet header field's `magic` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ magic_field, (uint64_t) magic_value);
+ }
+end:
+ bt_ctf_object_put_ref(magic_field);
+ return ret;
+}
+
+static
+int set_packet_header_uuid(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ int64_t i;
+ struct bt_ctf_trace *trace = NULL;
+ struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_header, "uuid");
+
+ BT_ASSERT(stream);
+
+ if (!uuid_field) {
+ /* No uuid field found. Not an error, skip. */
+ BT_LOGV("No field named `uuid` in packet header: skipping: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ trace = (struct bt_ctf_trace *)
+ bt_ctf_object_get_parent(&stream->common.base);
+
+ for (i = 0; i < 16; i++) {
+ struct bt_ctf_field *uuid_element =
+ bt_ctf_field_array_get_field(uuid_field, i);
+
+ ret = bt_ctf_field_integer_unsigned_set_value(
+ uuid_element, (uint64_t) trace->common.uuid[i]);
+ bt_ctf_object_put_ref(uuid_element);
+ if (ret) {
+ BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
+ "value=%" PRIu64 ", index=%" PRId64,
+ stream, bt_ctf_stream_get_name(stream),
+ uuid_element, (uint64_t) trace->common.uuid[i], i);
+ goto end;
+ }
+ }
+
+ BT_LOGV("Set packet header field's `uuid` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), uuid_field);
+
+end:
+ bt_ctf_object_put_ref(uuid_field);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
+ return ret;
+}
+static
+int set_packet_header_stream_id(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ uint32_t stream_id;
+ struct bt_ctf_field *stream_id_field =
+ bt_ctf_field_structure_get_field_by_name(
+ stream->packet_header, "stream_id");
+
+ if (!stream_id_field) {
+ /* No stream_id field found. Not an error, skip. */
+ BT_LOGV("No field named `stream_id` in packet header: skipping: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ stream_id = stream->common.stream_class->id;
+ ret = bt_ctf_field_integer_unsigned_set_value(stream_id_field,
+ (uint64_t) stream_id);
+ if (ret) {
+ BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ stream_id_field, (uint64_t) stream_id);
+ } else {
+ BT_LOGV("Set packet header field's `stream_id` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ stream_id_field, (uint64_t) stream_id);
+ }
+
+end:
+ bt_ctf_object_put_ref(stream_id_field);
+ return ret;
+}
+
+static
+int auto_populate_packet_header(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+
+ if (!stream->packet_header) {
+ goto end;
+ }
+
+ ret = set_packet_header_magic(stream);
+ if (ret) {
+ BT_LOGW("Cannot set packet header's magic number field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ ret = set_packet_header_uuid(stream);
+ if (ret) {
+ BT_LOGW("Cannot set packet header's UUID field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ ret = set_packet_header_stream_id(stream);
+ if (ret) {
+ BT_LOGW("Cannot set packet header's stream class ID field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ BT_LOGV("Automatically populated stream's packet header's known fields: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+
+end:
+ return ret;
+}
+
+static
+int set_packet_context_packet_size(struct bt_ctf_stream *stream,
+ uint64_t packet_size_bits)
+{
+ int ret = 0;
+ struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "packet_size");
+
+ ret = bt_ctf_field_integer_unsigned_set_value(field, packet_size_bits);
+ if (ret) {
+ BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, packet_size_bits);
+ } else {
+ BT_LOGV("Set packet context field's `packet_size` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, packet_size_bits);
+ }
+
+ bt_ctf_object_put_ref(field);
+ return ret;
+}
+
+static
+int set_packet_context_content_size(struct bt_ctf_stream *stream,
+ uint64_t content_size_bits)
+{
+ int ret = 0;
+ struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "content_size");
+
+ BT_ASSERT(stream);
+
+ if (!field) {
+ /* No content size field found. Not an error, skip. */
+ BT_LOGV("No field named `content_size` in packet context: skipping: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ ret = bt_ctf_field_integer_unsigned_set_value(field, content_size_bits);
+ if (ret) {
+ BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, content_size_bits);
+ } else {
+ BT_LOGV("Set packet context field's `content_size` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, content_size_bits);
+ }
+
+end:
+ bt_ctf_object_put_ref(field);
+ return ret;
+}
+
+static
+int set_packet_context_events_discarded(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "events_discarded");
+
+ BT_ASSERT(stream);
+
+ if (!field) {
+ /* No discarded events count field found. Not an error, skip. */
+ BT_LOGV("No field named `events_discarded` in packet context: skipping: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ /*
+ * If the field is set by the user, make sure that the value is
+ * greater than or equal to the stream's current count of
+ * discarded events. We do not allow wrapping here. If it's
+ * valid, update the stream's current count.
+ */
+ if (bt_ctf_field_is_set_recursive(field)) {
+ uint64_t user_val;
+
+ ret = bt_ctf_field_integer_unsigned_get_value(field,
+ &user_val);
+ if (ret) {
+ BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), field);
+ goto end;
+ }
+
+ if (user_val < stream->discarded_events) {
+ BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
+ "value is lesser than the stream's current discarded events count: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
+ "value=%" PRIu64 ", "
+ "stream-discarded-events-count=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream), field,
+ user_val, stream->discarded_events);
+ goto end;
+ }
+
+ stream->discarded_events = user_val;
+ } else {
+ ret = bt_ctf_field_integer_unsigned_set_value(field,
+ stream->discarded_events);
+ if (ret) {
+ BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, stream->discarded_events);
+ } else {
+ BT_LOGV("Set packet context field's `events_discarded` field's value: "
+ "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ field, stream->discarded_events);
+ }
+ }
+
+end:
+ bt_ctf_object_put_ref(field);
+ return ret;
+}
+
+static
+void update_clock_value(uint64_t *val, uint64_t new_val,
+ unsigned int new_val_size)
+{
+ const uint64_t pow2 = 1ULL << new_val_size;
+ const uint64_t mask = pow2 - 1;
+ uint64_t val_masked;
+
+#ifdef BT_LOG_ENABLED_VERBOSE
+ uint64_t old_val = *val;
+#endif
+
+ if (new_val_size == 64) {
+ *val = new_val;
+ goto end;
+ }
+
+ val_masked = *val & mask;
+
+ if (new_val < val_masked) {
+ /* Wrapped once */
+ new_val |= pow2;
+ }
+
+ *val &= ~mask;
+ *val |= new_val;
+
+end:
+ BT_LOGV("Updated clock value: old-val=%" PRIu64 ", new-val=%" PRIu64,
+ old_val, *val);
+ return;
+}
+
+static
+int visit_field_update_clock_value(struct bt_ctf_field *field, uint64_t *val)
+{
+ int ret = 0;
+ struct bt_ctf_field_common *field_common = (void *) field;
+
+ if (!field) {
+ goto end;
+ }
+
+ switch (bt_ctf_field_get_type_id(field)) {
+ case BT_CTF_FIELD_TYPE_ID_INTEGER:
+ {
+ struct bt_ctf_clock_class *cc =
+ bt_ctf_field_type_integer_get_mapped_clock_class(
+ (void *) field_common->type);
+ int val_size;
+ uint64_t uval;
+
+ if (!cc) {
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(cc);
+ val_size = bt_ctf_field_type_integer_get_size(
+ (void *) field_common->type);
+ BT_ASSERT(val_size >= 1);
+
+ if (bt_ctf_field_type_integer_is_signed(
+ (void *) field_common->type)) {
+ int64_t ival;
+
+ ret = bt_ctf_field_integer_signed_get_value(field, &ival);
+ uval = (uint64_t) ival;
+ } else {
+ ret = bt_ctf_field_integer_unsigned_get_value(field, &uval);
+ }
+
+ if (ret) {
+ /* Not set */
+ goto end;
+ }
+
+ update_clock_value(val, uval, val_size);
+ break;
+ }
+ case BT_CTF_FIELD_TYPE_ID_ENUM:
+ {
+ struct bt_ctf_field *int_field =
+ bt_ctf_field_enumeration_get_container(field);
+
+ BT_ASSERT(int_field);
+ ret = visit_field_update_clock_value(int_field, val);
+ bt_ctf_object_put_ref(int_field);
+ break;
+ }
+ case BT_CTF_FIELD_TYPE_ID_ARRAY:
+ {
+ uint64_t i;
+ int64_t len = bt_ctf_field_type_array_get_length(
+ (void *) field_common->type);
+
+ BT_ASSERT(len >= 0);
+
+ for (i = 0; i < len; i++) {
+ struct bt_ctf_field *elem_field =
+ bt_ctf_field_array_get_field(field, i);
+
+ BT_ASSERT(elem_field);
+ ret = visit_field_update_clock_value(elem_field, val);
+ bt_ctf_object_put_ref(elem_field);
+ if (ret) {
+ goto end;
+ }
+ }
+ break;
+ }
+ case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ uint64_t i;
+ int64_t len = bt_ctf_field_common_sequence_get_length(
+ (void *) field);
+
+ if (len < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < len; i++) {
+ struct bt_ctf_field *elem_field =
+ bt_ctf_field_sequence_get_field(field, i);
+
+ BT_ASSERT(elem_field);
+ ret = visit_field_update_clock_value(elem_field, val);
+ bt_ctf_object_put_ref(elem_field);
+ if (ret) {
+ goto end;
+ }
+ }
+ break;
+ }
+ case BT_CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ uint64_t i;
+ int64_t len = bt_ctf_field_type_structure_get_field_count(
+ (void *) field_common->type);
+
+ BT_ASSERT(len >= 0);
+
+ for (i = 0; i < len; i++) {
+ struct bt_ctf_field *member_field =
+ bt_ctf_field_structure_get_field_by_index(field, i);
+
+ BT_ASSERT(member_field);
+ ret = visit_field_update_clock_value(member_field, val);
+ bt_ctf_object_put_ref(member_field);
+ if (ret) {
+ goto end;
+ }
+ }
+ break;
+ }
+ case BT_CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_ctf_field *cur_field =
+ bt_ctf_field_variant_get_current_field(field);
+
+ if (!cur_field) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = visit_field_update_clock_value(cur_field, val);
+ bt_ctf_object_put_ref(cur_field);
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+int visit_event_update_clock_value(struct bt_ctf_event *event, uint64_t *val)
+{
+ int ret = 0;
+ struct bt_ctf_field *field;
+
+ field = bt_ctf_event_get_header(event);
+ ret = visit_field_update_clock_value(field, val);
+ bt_ctf_object_put_ref(field);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically update clock value in "
+ "event's header.");
+ goto end;
+ }
+
+ field = bt_ctf_event_get_stream_event_context(event);
+ ret = visit_field_update_clock_value(field, val);
+ bt_ctf_object_put_ref(field);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically update clock value in "
+ "event's stream event context.");
+ goto end;
+ }
+
+ field = bt_ctf_event_get_context(event);
+ ret = visit_field_update_clock_value(field, val);
+ bt_ctf_object_put_ref(field);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically update clock value in "
+ "event's context.");
+ goto end;
+ }
+
+ field = bt_ctf_event_get_payload_field(event);
+ ret = visit_field_update_clock_value(field, val);
+ bt_ctf_object_put_ref(field);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically update clock value in "
+ "event's payload.");
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int set_packet_context_timestamps(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ uint64_t val;
+ uint64_t cur_clock_value;
+ uint64_t init_clock_value = 0;
+ struct bt_ctf_field *ts_begin_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "timestamp_begin");
+ struct bt_ctf_field *ts_end_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "timestamp_end");
+ struct bt_ctf_field_common *packet_context =
+ (void *) stream->packet_context;
+ uint64_t i;
+ int64_t len;
+
+ if (ts_begin_field && bt_ctf_field_is_set_recursive(ts_begin_field)) {
+ /* Use provided `timestamp_begin` value as starting value */
+ ret = bt_ctf_field_integer_unsigned_get_value(ts_begin_field, &val);
+ BT_ASSERT(ret == 0);
+ init_clock_value = val;
+ } else if (stream->last_ts_end != -1ULL) {
+ /* Use last packet's ending timestamp as starting value */
+ init_clock_value = stream->last_ts_end;
+ }
+
+ cur_clock_value = init_clock_value;
+
+ if (stream->last_ts_end != -1ULL &&
+ cur_clock_value < stream->last_ts_end) {
+ BT_LOGW("Packet's initial timestamp is less than previous "
+ "packet's final timestamp: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "cur-packet-ts-begin=%" PRIu64 ", "
+ "prev-packet-ts-end=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ cur_clock_value, stream->last_ts_end);
+ ret = -1;
+ goto end;
+ }
+
+ /*
+ * Visit all the packet context fields, followed by all the
+ * fields of all the events, in order, updating our current
+ * clock value as we visit.
+ *
+ * While visiting the packet context fields, do not consider
+ * `timestamp_begin` and `timestamp_end` because this function's
+ * purpose is to set them anyway. Also do not consider
+ * `packet_size`, `content_size`, `events_discarded`, and
+ * `packet_seq_num` if they are not set because those are
+ * autopopulating fields.
+ */
+ len = bt_ctf_field_type_structure_get_field_count(
+ (void *) packet_context->type);
+ BT_ASSERT(len >= 0);
+
+ for (i = 0; i < len; i++) {
+ const char *member_name;
+ struct bt_ctf_field *member_field;
+
+ ret = bt_ctf_field_type_structure_get_field_by_index(
+ (void *) packet_context->type, &member_name, NULL, i);
+ BT_ASSERT(ret == 0);
+
+ if (strcmp(member_name, "timestamp_begin") == 0 ||
+ strcmp(member_name, "timestamp_end") == 0) {
+ continue;
+ }
+
+ member_field = bt_ctf_field_structure_get_field_by_index(
+ stream->packet_context, i);
+ BT_ASSERT(member_field);
+
+ if (strcmp(member_name, "packet_size") == 0 &&
+ !bt_ctf_field_is_set_recursive(member_field)) {
+ bt_ctf_object_put_ref(member_field);
+ continue;
+ }
+
+ if (strcmp(member_name, "content_size") == 0 &&
+ !bt_ctf_field_is_set_recursive(member_field)) {
+ bt_ctf_object_put_ref(member_field);
+ continue;
+ }
+
+ if (strcmp(member_name, "events_discarded") == 0 &&
+ !bt_ctf_field_is_set_recursive(member_field)) {
+ bt_ctf_object_put_ref(member_field);
+ continue;
+ }
+
+ if (strcmp(member_name, "packet_seq_num") == 0 &&
+ !bt_ctf_field_is_set_recursive(member_field)) {
+ bt_ctf_object_put_ref(member_field);
+ continue;
+ }
+
+ ret = visit_field_update_clock_value(member_field,
+ &cur_clock_value);
+ bt_ctf_object_put_ref(member_field);
+ if (ret) {
+ BT_LOGW("Cannot automatically update clock value "
+ "in stream's packet context: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "field-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream),
+ member_name);
+ goto end;
+ }
+ }
+
+ for (i = 0; i < stream->events->len; i++) {
+ struct bt_ctf_event *event = g_ptr_array_index(stream->events, i);
+
+ BT_ASSERT(event);
+ ret = visit_event_update_clock_value(event, &cur_clock_value);
+ if (ret) {
+ BT_LOGW("Cannot automatically update clock value "
+ "in stream's packet context: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "index=%" PRIu64 ", event-addr=%p, "
+ "event-class-id=%" PRId64 ", "
+ "event-class-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream),
+ i, event,
+ bt_ctf_event_class_common_get_id(event->common.class),
+ bt_ctf_event_class_common_get_name(event->common.class));
+ goto end;
+ }
+ }
+
+ /*
+ * Everything is visited, thus the current clock value
+ * corresponds to the ending timestamp. Validate this value
+ * against the provided value of `timestamp_end`, if any,
+ * otherwise set it.
+ */
+ if (ts_end_field && bt_ctf_field_is_set_recursive(ts_end_field)) {
+ ret = bt_ctf_field_integer_unsigned_get_value(ts_end_field, &val);
+ BT_ASSERT(ret == 0);
+
+ if (val < cur_clock_value) {
+ BT_LOGW("Packet's final timestamp is less than "
+ "computed packet's final timestamp: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "cur-packet-ts-end=%" PRIu64 ", "
+ "computed-packet-ts-end=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream),
+ val, cur_clock_value);
+ ret = -1;
+ goto end;
+ }
+
+ stream->last_ts_end = val;
+ }
+
+ if (ts_end_field && !bt_ctf_field_is_set_recursive(ts_end_field)) {
+ ret = set_integer_field_value(ts_end_field, cur_clock_value);
+ BT_ASSERT(ret == 0);
+ stream->last_ts_end = cur_clock_value;
+ }
+
+ if (!ts_end_field) {
+ stream->last_ts_end = cur_clock_value;
+ }
+
+ /* Set `timestamp_begin` field to initial clock value */
+ if (ts_begin_field && !bt_ctf_field_is_set_recursive(ts_begin_field)) {
+ ret = set_integer_field_value(ts_begin_field, init_clock_value);
+ BT_ASSERT(ret == 0);
+ }
+
+end:
+ bt_ctf_object_put_ref(ts_begin_field);
+ bt_ctf_object_put_ref(ts_end_field);
+ return ret;
+}
+
+static
+int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts,
+ uint64_t packet_size_bits, uint64_t content_size_bits)
+{
+ int ret = 0;
+
+ if (!stream->packet_context) {
+ goto end;
+ }
+
+ ret = set_packet_context_packet_size(stream, packet_size_bits);
+ if (ret) {
+ BT_LOGW("Cannot set packet context's packet size field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ ret = set_packet_context_content_size(stream, content_size_bits);
+ if (ret) {
+ BT_LOGW("Cannot set packet context's content size field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ if (set_ts) {
+ ret = set_packet_context_timestamps(stream);
+ if (ret) {
+ BT_LOGW("Cannot set packet context's timestamp fields: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+ }
+
+ ret = set_packet_context_events_discarded(stream);
+ if (ret) {
+ BT_LOGW("Cannot set packet context's discarded events count field: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+ goto end;
+ }
+
+ BT_LOGV("Automatically populated stream's packet context's known fields: "
+ "stream-addr=%p, stream-name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+
+end:
+ return ret;
+}
+
+static
+void release_event(struct bt_ctf_event *event)
+{
+ if (bt_ctf_object_get_ref_count(&event->common.base)) {
+ /*
+ * The event is being orphaned, but it must guarantee the
+ * existence of its event class for the duration of its
+ * lifetime.
+ */
+ bt_ctf_object_get_ref(event->common.class);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(event->common.base.parent);
+ } else {
+ bt_ctf_object_try_spec_release(&event->common.base);
+ }
+}
+
+static
+int create_stream_file(struct bt_ctf_writer *writer,
+ struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ GString *filename = g_string_new(NULL);
+ int64_t stream_class_id;
+ char *file_path = NULL;
+
+ BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
+ "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
+ writer, stream, bt_ctf_stream_get_name(stream),
+ stream->common.stream_class,
+ stream->common.stream_class->name->str);
+
+ if (stream->common.name && stream->common.name->len > 0) {
+ /* Use stream name's base name as prefix */
+ gchar *basename = g_path_get_basename(stream->common.name->str);
+
+ BT_ASSERT(basename);
+
+ if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
+ g_string_assign(filename, "stream");
+ } else {
+ g_string_assign(filename, basename);
+ }
+
+ g_free(basename);
+ goto append_ids;
+ }
+
+ if (stream->common.stream_class->name &&
+ stream->common.stream_class->name->len > 0) {
+ /* Use stream class name's base name as prefix */
+ gchar *basename =
+ g_path_get_basename(
+ stream->common.stream_class->name->str);
+
+ BT_ASSERT(basename);
+
+ if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
+ g_string_assign(filename, "stream");
+ } else {
+ g_string_assign(filename, basename);
+ }
+
+ g_free(basename);
+ goto append_ids;
+ }
+
+ /* Default to using `stream-` as prefix */
+ g_string_assign(filename, "stream");
+
+append_ids:
+ stream_class_id = bt_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,
+ stream_class_id, stream->common.id);
+
+ file_path = g_build_filename(writer->path->str, filename->str, NULL);
+ if (file_path == NULL) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctfser_init(&stream->ctfser, file_path);
+ g_free(file_path);
+ if (ret) {
+ /* bt_ctfser_init() logs errors */
+ goto end;
+ }
+
+ BT_LOGD("Created stream file for writing: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "filename=\"%s\"", stream, bt_ctf_stream_get_name(stream),
+ filename->str);
+
+end:
+ g_string_free(filename, TRUE);
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_stream_create_with_id(
+ struct bt_ctf_stream_class *stream_class,
+ const char *name, uint64_t id)
+{
+ int ret;
+ int fd;
+ struct bt_ctf_stream *stream = NULL;
+ struct bt_ctf_trace *trace = NULL;
+ struct bt_ctf_writer *writer = NULL;
+
+ BT_LOGD("Creating CTF writer stream object: stream-class-addr=%p, "
+ "stream-class-name=\"%s\", stream-name=\"%s\", "
+ "stream-id=%" PRIu64,
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ name, id);
+ stream = g_new0(struct bt_ctf_stream, 1);
+ if (!stream) {
+ BT_LOGE_STR("Failed to allocate one stream.");
+ goto error;
+ }
+
+ if (id == -1ULL) {
+ id = stream_class->next_stream_id;
+ }
+
+ ret = bt_ctf_stream_common_initialize(BT_CTF_TO_COMMON(stream),
+ BT_CTF_TO_COMMON(stream_class), name, id, bt_ctf_stream_destroy);
+ if (ret) {
+ /* bt_ctf_stream_common_initialize() logs errors */
+ goto error;
+ }
+
+ 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\", "
+ "stream-name=\"%s\"",
+ stream_class, bt_ctf_stream_class_get_name(stream_class),
+ name);
+ goto error;
+ }
+
+ writer = (struct bt_ctf_writer *)
+ bt_ctf_object_get_parent(&trace->common.base);
+ stream->last_ts_end = -1ULL;
+ BT_LOGD("CTF writer stream object belongs writer's trace: "
+ "writer-addr=%p", writer);
+ BT_ASSERT(writer);
+
+ if (stream_class->common.packet_context_field_type) {
+ BT_LOGD("Creating stream's packet context field: "
+ "ft-addr=%p",
+ stream_class->common.packet_context_field_type);
+ stream->packet_context = bt_ctf_field_create(
+ (void *) stream_class->common.packet_context_field_type);
+ if (!stream->packet_context) {
+ BT_LOGW_STR("Cannot create stream's packet context field.");
+ goto error;
+ }
+
+ /* Initialize events_discarded */
+ ret = try_set_structure_field_integer(
+ stream->packet_context, "events_discarded", 0);
+ if (ret < 0) {
+ BT_LOGW("Cannot set `events_discarded` field in packet context: "
+ "ret=%d, packet-context-field-addr=%p",
+ ret, stream->packet_context);
+ goto error;
+ }
+ }
+
+ stream->events = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) release_event);
+ if (!stream->events) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ goto error;
+ }
+
+ if (trace->common.packet_header_field_type) {
+ BT_LOGD("Creating stream's packet header field: "
+ "ft-addr=%p", trace->common.packet_header_field_type);
+ stream->packet_header =
+ bt_ctf_field_create(
+ (void *) trace->common.packet_header_field_type);
+ if (!stream->packet_header) {
+ BT_LOGW_STR("Cannot create stream's packet header field.");
+ goto error;
+ }
+ }
+
+ /*
+ * Attempt to populate the default trace packet header fields
+ * (magic, uuid and stream_id). This will _not_ fail shall the
+ * fields not be found or be of an incompatible type; they will
+ * simply not be populated automatically. The user will have to
+ * make sure to set the trace packet header fields himself
+ * before flushing.
+ */
+ ret = auto_populate_packet_header(stream);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
+ goto error;
+ }
+
+ /* Create file associated with this stream */
+ fd = create_stream_file(writer, stream);
+ if (fd < 0) {
+ BT_LOGW_STR("Cannot create stream file.");
+ goto error;
+ }
+
+ /* Freeze the writer */
+ BT_LOGD_STR("Freezing stream's CTF writer.");
+ bt_ctf_writer_freeze(writer);
+
+ /* Add this stream to the trace's streams */
+ g_ptr_array_add(trace->common.streams, stream);
+ stream_class->next_stream_id++;
+ BT_LOGD("Created stream object: addr=%p", stream);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(stream);
+
+end:
+ bt_ctf_object_put_ref(writer);
+ return stream;
+}
+
+struct bt_ctf_stream *bt_ctf_stream_create(
+ struct bt_ctf_stream_class *stream_class,
+ const char *name, uint64_t id_param)
+{
+ return bt_ctf_stream_create_with_id(stream_class,
+ name, id_param);
+}
+
+int bt_ctf_stream_get_discarded_events_count(
+ struct bt_ctf_stream *stream, uint64_t *count)
+{
+ int ret = 0;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!count) {
+ BT_LOGW_STR("Invalid parameter: count is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ *count = (uint64_t) stream->discarded_events;
+
+end:
+ return ret;
+}
+
+static
+int set_packet_context_events_discarded_field(struct bt_ctf_stream *stream,
+ uint64_t count)
+{
+ int ret = 0;
+ struct bt_ctf_field *events_discarded_field = NULL;
+
+ if (!stream->packet_context) {
+ goto end;
+ }
+
+ events_discarded_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "events_discarded");
+ if (!events_discarded_field) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_integer_unsigned_set_value(
+ events_discarded_field, count);
+ if (ret) {
+ BT_LOGW("Cannot set packet context's `events_discarded` field: "
+ "field-addr=%p, value=%" PRIu64,
+ events_discarded_field, count);
+ goto end;
+ }
+
+end:
+ bt_ctf_object_put_ref(events_discarded_field);
+ return ret;
+}
+
+void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
+ uint64_t event_count)
+{
+ int ret;
+ uint64_t new_count;
+ struct bt_ctf_field *events_discarded_field = NULL;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ goto end;
+ }
+
+ BT_LOGV("Appending discarded events to stream: "
+ "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream), event_count);
+
+ if (!stream->packet_context) {
+ BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
+ goto end;
+ }
+
+ events_discarded_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "events_discarded");
+ if (!events_discarded_field) {
+ BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
+ goto end;
+ }
+
+ new_count = stream->discarded_events + event_count;
+ if (new_count < stream->discarded_events) {
+ BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
+ "cur-count=%" PRIu64 ", new-count=%" PRIu64,
+ stream->discarded_events, new_count);
+ goto end;
+ }
+
+ ret = set_packet_context_events_discarded_field(stream, new_count);
+ if (ret) {
+ /* set_packet_context_events_discarded_field() logs errors */
+ goto end;
+ }
+
+ stream->discarded_events = new_count;
+ BT_LOGV("Appended discarded events to stream: "
+ "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
+ stream, bt_ctf_stream_get_name(stream), event_count);
+
+end:
+ bt_ctf_object_put_ref(events_discarded_field);
+}
+
+static int auto_populate_event_header(struct bt_ctf_stream *stream,
+ struct bt_ctf_event *event)
+{
+ int ret = 0;
+ struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
+ struct bt_ctf_clock_class *mapped_clock_class = NULL;
+ struct bt_ctf_stream_class *stream_class =
+ BT_CTF_FROM_COMMON(bt_ctf_stream_common_borrow_class(
+ BT_CTF_TO_COMMON(stream)));
+ int64_t event_class_id;
+
+ BT_ASSERT(event);
+
+ if (!event->common.header_field) {
+ goto end;
+ }
+
+ if (event->common.frozen) {
+ BT_LOGW_STR("Cannot populate event header field: event is frozen.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_LOGV("Automatically populating event's header field: "
+ "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), event);
+
+ id_field = bt_ctf_field_structure_get_field_by_name(
+ (void *) event->common.header_field->field, "id");
+ 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) {
+ ret = set_integer_field_value(id_field, event_class_id);
+ if (ret) {
+ BT_LOGW("Cannot set event header's `id` field's value: "
+ "addr=%p, value=%" PRIu64, id_field,
+ event_class_id);
+ goto end;
+ }
+ }
+
+ /*
+ * The conditions to automatically set the timestamp are:
+ *
+ * 1. The event header field "timestamp" exists and is an
+ * integer field.
+ * 2. This stream's class has a registered clock (set with
+ * bt_ctf_stream_class_set_clock()).
+ * 3. The "timestamp" field is not set.
+ */
+ timestamp_field = bt_ctf_field_structure_get_field_by_name(
+ (void *) event->common.header_field->field, "timestamp");
+ if (timestamp_field && stream_class->clock &&
+ bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER &&
+ !bt_ctf_field_is_set_recursive(timestamp_field)) {
+ mapped_clock_class =
+ bt_ctf_field_type_integer_get_mapped_clock_class(
+ (void *) ((struct bt_ctf_field_common *) timestamp_field)->type);
+ if (mapped_clock_class) {
+ uint64_t timestamp;
+
+ BT_ASSERT(mapped_clock_class ==
+ stream_class->clock->clock_class);
+ ret = bt_ctf_clock_get_value(
+ stream_class->clock,
+ ×tamp);
+ BT_ASSERT(ret == 0);
+ ret = set_integer_field_value(timestamp_field,
+ timestamp);
+ if (ret) {
+ BT_LOGW("Cannot set event header's `timestamp` field's value: "
+ "addr=%p, value=%" PRIu64,
+ timestamp_field, timestamp);
+ goto end;
+ }
+ }
+ }
+
+ BT_LOGV("Automatically populated event's header field: "
+ "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), event);
+
+end:
+ bt_ctf_object_put_ref(id_field);
+ bt_ctf_object_put_ref(timestamp_field);
+ bt_ctf_object_put_ref(mapped_clock_class);
+ return ret;
+}
+
+int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
+ struct bt_ctf_event *event)
+{
+ int ret = 0;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!event) {
+ BT_LOGW_STR("Invalid parameter: event is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_LOGV("Appending event to stream: "
+ "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ stream, bt_ctf_stream_get_name(stream), event,
+ bt_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
+ * point. The only other way an event can have a parent stream
+ * is if it was assigned when setting a packet to the event,
+ * in which case the packet's stream is not a writer stream,
+ * and thus the user is trying to append an event which belongs
+ * to another stream.
+ */
+ if (event->common.base.parent) {
+ ret = -1;
+ goto end;
+ }
+
+ bt_ctf_object_set_parent(&event->common.base, &stream->common.base);
+ BT_LOGV_STR("Automatically populating the header of the event to append.");
+ ret = auto_populate_event_header(stream, event);
+ if (ret) {
+ /* auto_populate_event_header() reports errors */
+ goto error;
+ }
+
+ /* Make sure the various scopes of the event are set */
+ BT_LOGV_STR("Validating event to append.");
+ BT_CTF_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_ctf_event_common_set_is_frozen(BT_CTF_TO_COMMON(event), true);
+ g_ptr_array_add(stream->events, event);
+
+ /*
+ * Event had to hold a reference to its event class as long as it wasn't
+ * part of the same trace hierarchy. From now on, the event and its
+ * class share the same lifetime guarantees and the reference is no
+ * longer needed.
+ */
+ BT_LOGV_STR("Putting the event's class.");
+ bt_ctf_object_put_ref(event->common.class);
+ BT_LOGV("Appended event to stream: "
+ "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
+ "event-class-name=\"%s\", event-class-id=%" PRId64,
+ stream, bt_ctf_stream_get_name(stream), event,
+ bt_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;
+
+error:
+ /*
+ * Orphan the event; we were not successful in associating it to
+ * a stream.
+ */
+ bt_ctf_object_set_parent(&event->common.base, NULL);
+ return ret;
+}
+
+struct bt_ctf_field *bt_ctf_stream_get_packet_context(struct bt_ctf_stream *stream)
+{
+ struct bt_ctf_field *packet_context = NULL;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ goto end;
+ }
+
+ packet_context = stream->packet_context;
+ if (packet_context) {
+ bt_ctf_object_get_ref(packet_context);
+ }
+end:
+ return packet_context;
+}
+
+int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
+ struct bt_ctf_field *field)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *field_type;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ field_type = bt_ctf_field_get_type(field);
+ 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\", "
+ "packet-context-field-addr=%p, "
+ "packet-context-ft-addr=%p",
+ stream, bt_ctf_stream_get_name(stream),
+ field, field_type);
+ ret = -1;
+ goto end;
+ }
+
+ bt_ctf_object_put_ref(field_type);
+ bt_ctf_object_put_ref(stream->packet_context);
+ stream->packet_context = bt_ctf_object_get_ref(field);
+ BT_LOGV("Set stream's packet context field: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "packet-context-field-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), field);
+end:
+ return ret;
+}
+
+struct bt_ctf_field *bt_ctf_stream_get_packet_header(struct bt_ctf_stream *stream)
+{
+ struct bt_ctf_field *packet_header = NULL;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ goto end;
+ }
+
+ packet_header = stream->packet_header;
+ if (packet_header) {
+ bt_ctf_object_get_ref(packet_header);
+ }
+end:
+ return packet_header;
+}
+
+int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
+ struct bt_ctf_field *field)
+{
+ int ret = 0;
+ struct bt_ctf_trace *trace = NULL;
+ struct bt_ctf_field_type *field_type = NULL;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ trace = (struct bt_ctf_trace *)
+ bt_ctf_object_get_parent(&stream->common.base);
+
+ if (!field) {
+ if (trace->common.packet_header_field_type) {
+ BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "packet-header-field-addr=%p, "
+ "expected-ft-addr=%p",
+ stream, bt_ctf_stream_get_name(stream),
+ field, trace->common.packet_header_field_type);
+ ret = -1;
+ goto end;
+ }
+
+ goto skip_validation;
+ }
+
+ field_type = bt_ctf_field_get_type(field);
+ BT_ASSERT(field_type);
+
+ if (bt_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\", "
+ "packet-header-field-addr=%p, "
+ "packet-header-ft-addr=%p",
+ stream, bt_ctf_stream_get_name(stream),
+ field, field_type);
+ ret = -1;
+ goto end;
+ }
+
+skip_validation:
+ bt_ctf_object_put_ref(stream->packet_header);
+ stream->packet_header = bt_ctf_object_get_ref(field);
+ BT_LOGV("Set stream's packet header field: "
+ "stream-addr=%p, stream-name=\"%s\", "
+ "packet-header-field-addr=%p",
+ stream, bt_ctf_stream_get_name(stream), field);
+end:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
+ bt_ctf_object_put_ref(field_type);
+ return ret;
+}
+
+static
+void reset_structure_field(struct bt_ctf_field *structure, const char *name)
+{
+ struct bt_ctf_field *member;
+
+ member = bt_ctf_field_structure_get_field_by_name(structure, name);
+ if (member) {
+ bt_ctf_field_common_reset_recursive((void *) member);
+ bt_ctf_object_put_ref(member);
+ }
+}
+
+int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
+{
+ int ret = 0;
+ size_t i;
+ uint64_t packet_context_offset_bits = 0;
+ struct bt_ctf_trace *trace;
+ enum bt_ctf_byte_order native_byte_order;
+ bool has_packet_size = false;
+ uint64_t packet_size_bits = 0;
+ uint64_t content_size_bits = 0;
+
+ if (!stream) {
+ BT_LOGW_STR("Invalid parameter: stream is NULL.");
+ ret = -1;
+ goto end_no_stream;
+ }
+
+ if (stream->packet_context) {
+ struct bt_ctf_field *packet_size_field;
+
+ packet_size_field = bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "packet_size");
+ has_packet_size = (packet_size_field != NULL);
+ bt_ctf_object_put_ref(packet_size_field);
+ }
+
+ if (stream->flushed_packet_count == 1) {
+ if (!stream->packet_context) {
+ BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!has_packet_size) {
+ BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
+ ret = -1;
+ goto end;
+ }
+ }
+
+ BT_LOGV("Flushing stream's current packet: stream-addr=%p, "
+ "stream-name=\"%s\", packet-index=%u", stream,
+ bt_ctf_stream_get_name(stream), stream->flushed_packet_count);
+ trace = BT_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);
+
+ ret = auto_populate_packet_header(stream);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Initialize packet/content sizes to `0`; we will overwrite later */
+ ret = auto_populate_packet_context(stream, true, 0, 0);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctfser_open_packet(&stream->ctfser);
+ if (ret) {
+ /* bt_ctfser_open_packet() logs errors */
+ ret = -1;
+ goto end;
+ }
+
+ if (stream->packet_header) {
+ BT_LOGV_STR("Serializing packet header field (initial).");
+ ret = bt_ctf_field_serialize_recursive(stream->packet_header,
+ &stream->ctfser, native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream's packet header field: "
+ "field-addr=%p", stream->packet_header);
+ goto end;
+ }
+ }
+
+ if (stream->packet_context) {
+ /* Save packet context's position to overwrite it later */
+ packet_context_offset_bits =
+ bt_ctfser_get_offset_in_current_packet_bits(
+ &stream->ctfser);
+
+ /* Write packet context */
+ BT_LOGV_STR("Serializing packet context field (initial).");
+ ret = bt_ctf_field_serialize_recursive(stream->packet_context,
+ &stream->ctfser, native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream's packet context field: "
+ "field-addr=%p", stream->packet_context);
+ goto end;
+ }
+ }
+
+ BT_LOGV("Serializing events: count=%u", stream->events->len);
+
+ for (i = 0; i < stream->events->len; i++) {
+ struct bt_ctf_event *event = g_ptr_array_index(
+ stream->events, i);
+ struct bt_ctf_event_class *event_class =
+ BT_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 ", "
+ "ser-offset=%" PRIu64,
+ i, event, bt_ctf_event_class_get_name(event_class),
+ bt_ctf_event_class_get_id(event_class),
+ bt_ctfser_get_offset_in_current_packet_bits(
+ &stream->ctfser));
+
+ /* Write event header */
+ if (event->common.header_field) {
+ BT_LOGV_STR("Serializing event's header field.");
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) event->common.header_field->field,
+ &stream->ctfser, native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize event's header field: "
+ "field-addr=%p",
+ event->common.header_field->field);
+ goto end;
+ }
+ }
+
+ /* Write stream event context */
+ if (event->common.stream_event_context_field) {
+ BT_LOGV_STR("Serializing event's stream event context field.");
+ ret = bt_ctf_field_serialize_recursive(
+ (void *) event->common.stream_event_context_field,
+ &stream->ctfser, native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize event's stream event context field: "
+ "field-addr=%p",
+ event->common.stream_event_context_field);
+ goto end;
+ }
+ }
+
+ /* Write event content */
+ ret = bt_ctf_event_serialize(event, &stream->ctfser,
+ native_byte_order);
+ if (ret) {
+ /* bt_ctf_event_serialize() logs errors */
+ goto end;
+ }
+ }
+
+ content_size_bits = bt_ctfser_get_offset_in_current_packet_bits(
+ &stream->ctfser);
+
+ if (!has_packet_size && content_size_bits % 8 != 0) {
+ BT_LOGW("Stream's packet context field type has no `packet_size` field, "
+ "but current content size is not a multiple of 8 bits: "
+ "content-size=%" PRIu64 ", "
+ "packet-size=%" PRIu64,
+ content_size_bits,
+ packet_size_bits);
+ ret = -1;
+ goto end;
+ }
+
+ /* Set packet size; make it a multiple of 8 */
+ packet_size_bits = (content_size_bits + 7) & ~UINT64_C(7);
+
+ if (stream->packet_context) {
+ /*
+ * The whole packet is serialized at this point. Make
+ * sure that, if `packet_size` is missing, the current
+ * content size is equal to the current packet size.
+ */
+ struct bt_ctf_field *field =
+ bt_ctf_field_structure_get_field_by_name(
+ stream->packet_context, "content_size");
+
+ bt_ctf_object_put_ref(field);
+ if (!field) {
+ if (content_size_bits != packet_size_bits) {
+ BT_LOGW("Stream's packet context's `content_size` field is missing, "
+ "but current packet's content size is not equal to its packet size: "
+ "content-size=%" PRIu64 ", "
+ "packet-size=%" PRIu64,
+ bt_ctfser_get_offset_in_current_packet_bits(&stream->ctfser),
+ packet_size_bits);
+ ret = -1;
+ goto end;
+ }
+ }
+
+ /*
+ * Overwrite the packet context now that the stream
+ * position's packet and content sizes have the correct
+ * values.
+ */
+ bt_ctfser_set_offset_in_current_packet_bits(&stream->ctfser,
+ packet_context_offset_bits);
+ ret = auto_populate_packet_context(stream, false,
+ packet_size_bits, content_size_bits);
+ if (ret) {
+ BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_LOGV("Rewriting (serializing) packet context field.");
+ ret = bt_ctf_field_serialize_recursive(stream->packet_context,
+ &stream->ctfser, native_byte_order);
+ if (ret) {
+ BT_LOGW("Cannot serialize stream's packet context field: "
+ "field-addr=%p", stream->packet_context);
+ goto end;
+ }
+ }
+
+ g_ptr_array_set_size(stream->events, 0);
+ stream->flushed_packet_count++;
+ bt_ctfser_close_current_packet(&stream->ctfser, packet_size_bits / 8);
+
+end:
+ /* Reset automatically-set fields. */
+ if (stream->packet_context) {
+ reset_structure_field(stream->packet_context, "timestamp_begin");
+ reset_structure_field(stream->packet_context, "timestamp_end");
+ reset_structure_field(stream->packet_context, "packet_size");
+ reset_structure_field(stream->packet_context, "content_size");
+ reset_structure_field(stream->packet_context, "events_discarded");
+ }
+
+ if (ret == 0) {
+ BT_LOGV("Flushed stream's current packet: "
+ "content-size=%" PRIu64 ", packet-size=%" PRIu64,
+ content_size_bits, packet_size_bits);
+ }
+
+end_no_stream:
+ return ret;
+}
+
+static
+void bt_ctf_stream_destroy(struct bt_ctf_object *obj)
+{
+ struct bt_ctf_stream *stream = (void *) obj;
+
+ BT_LOGD("Destroying CTF writer stream object: addr=%p, name=\"%s\"",
+ stream, bt_ctf_stream_get_name(stream));
+
+ bt_ctf_stream_common_finalize(BT_CTF_TO_COMMON(stream));
+ bt_ctfser_fini(&stream->ctfser);
+
+ if (stream->events) {
+ BT_LOGD_STR("Putting events.");
+ g_ptr_array_free(stream->events, TRUE);
+ }
+
+ BT_LOGD_STR("Putting packet header field.");
+ bt_ctf_object_put_ref(stream->packet_header);
+ BT_LOGD_STR("Putting packet context field.");
+ bt_ctf_object_put_ref(stream->packet_context);
+ g_free(stream);
+}
+
+static
+int _set_structure_field_integer(struct bt_ctf_field *structure, char *name,
+ uint64_t value, bt_bool force)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *field_type = NULL;
+ struct bt_ctf_field *integer;
+
+ BT_ASSERT(structure);
+ BT_ASSERT(name);
+
+ integer = bt_ctf_field_structure_get_field_by_name(structure, name);
+ if (!integer) {
+ /* Field not found, not an error. */
+ BT_LOGV("Field not found: struct-field-addr=%p, "
+ "name=\"%s\", force=%d", structure, name, force);
+ goto end;
+ }
+
+ /* Make sure the payload has not already been set. */
+ if (!force && bt_ctf_field_is_set_recursive(integer)) {
+ /* Payload already set, not an error */
+ BT_LOGV("Field's payload is already set: struct-field-addr=%p, "
+ "name=\"%s\", force=%d", structure, name, force);
+ goto end;
+ }
+
+ field_type = bt_ctf_field_get_type(integer);
+ BT_ASSERT(field_type);
+ if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+ /*
+ * The user most likely meant for us to populate this field
+ * automatically. However, we can only do this if the field
+ * is an integer. Return an error.
+ */
+ BT_LOGW("Invalid parameter: field's type is not an integer field type: "
+ "field-addr=%p, ft-addr=%p, ft-id=%s",
+ integer, field_type,
+ bt_ctf_field_type_id_string((int)
+ bt_ctf_field_type_get_type_id(field_type)));
+ ret = -1;
+ goto end;
+ }
+
+ if (bt_ctf_field_type_integer_is_signed(field_type)) {
+ ret = bt_ctf_field_integer_signed_set_value(integer,
+ (int64_t) value);
+ } else {
+ ret = bt_ctf_field_integer_unsigned_set_value(integer, value);
+ }
+ ret = !ret ? 1 : ret;
+end:
+ bt_ctf_object_put_ref(integer);
+ bt_ctf_object_put_ref(field_type);
+ return ret;
+}
+
+/*
+ * Returns the following codes:
+ * 1 if the field was found and set,
+ * 0 if nothing was done (field not found, or was already set),
+ * <0 if an error was encoutered
+ */
+static
+int try_set_structure_field_integer(struct bt_ctf_field *structure, char *name,
+ uint64_t value)
+{
+ return _set_structure_field_integer(structure, name, value, BT_FALSE);
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_get_class(
+ struct bt_ctf_stream *stream)
+{
+ return bt_ctf_object_get_ref(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_ctf_stream_common_get_name(BT_CTF_TO_COMMON(stream));
+}
+
+int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream)
+{
+ return bt_ctf_stream_common_get_id(BT_CTF_TO_COMMON(stream));
+}
--- /dev/null
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-TRACE"
+#include "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/attributes-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/event.h>
+#include <babeltrace2/ctf-writer/event-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace2/ctf-writer/functor-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/stream-internal.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/utils-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/validation-internal.h>
+#include <babeltrace2/ctf-writer/visitor-internal.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/ctf-writer/values-internal.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_ctf_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_ctf_object_init_shared_with_parent(&trace->base, release_func);
+ trace->clock_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ 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_ctf_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_ctf_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_ctf_object_put_ref(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_ctf_private_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_ctf_value_is_integer(bt_ctf_private_value_as_value(value)) &&
+ !bt_ctf_value_is_string(bt_ctf_private_value_as_value(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_ctf_value_type_string(
+ bt_ctf_value_get_type(
+ bt_ctf_private_value_as_value(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_ctf_private_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_ctf_value_freeze(bt_ctf_private_value_as_value(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_ctf_private_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_ctf_private_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_ctf_object_put_ref(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_ctf_private_value *env_value_integer_obj = NULL;
+
+ env_value_integer_obj = bt_ctf_private_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_ctf_object_put_ref(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_ctf_object_get_ref(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;
+ }
+ }
+ }
+
+ /*
+ * 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_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_CTF_OBJECT_MOVE_REF(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_ctf_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_ctf_object_put_ref(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_ctf_object_put_ref(trace->packet_header_field_type);
+ trace->packet_header_field_type = bt_ctf_object_get_ref(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 = bt_ctf_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_ctf_object *obj)
+{
+ struct bt_ctf_trace *trace = (void *) obj;
+
+ BT_LOGD("Destroying CTF writer trace object: addr=%p, name=\"%s\"",
+ trace, bt_ctf_trace_get_name(trace));
+ bt_ctf_trace_common_finalize(BT_CTF_TO_COMMON(trace));
+ g_free(trace);
+}
+
+BT_HIDDEN
+struct bt_ctf_trace *bt_ctf_trace_create(void)
+{
+ struct bt_ctf_trace *trace = NULL;
+ int ret;
+
+ BT_LOGD_STR("Creating CTF writer trace object.");
+ trace = g_new0(struct bt_ctf_trace, 1);
+ if (!trace) {
+ BT_LOGE_STR("Failed to allocate one CTF writer trace.");
+ goto error;
+ }
+
+ ret = bt_ctf_trace_common_initialize(BT_CTF_TO_COMMON(trace),
+ bt_ctf_trace_destroy);
+ if (ret) {
+ /* bt_ctf_trace_common_initialize() logs errors */
+ goto error;
+ }
+
+ BT_LOGD("Created CTF writer trace object: addr=%p", trace);
+ return trace;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
+ return trace;
+}
+
+const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *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_ctf_trace_common_set_uuid(BT_CTF_TO_COMMON(trace), uuid);
+}
+
+int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
+ const char *name, const char *value)
+{
+ 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_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_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_ctf_trace_common_get_environment_field_name_by_index(
+ BT_CTF_TO_COMMON(trace), index);
+}
+
+struct bt_ctf_value *bt_ctf_trace_get_environment_field_value_by_index(
+ struct bt_ctf_trace *trace, uint64_t index)
+{
+ return bt_ctf_object_get_ref(bt_ctf_trace_common_borrow_environment_field_value_by_index(
+ BT_CTF_TO_COMMON(trace), index));
+}
+
+struct bt_ctf_value *bt_ctf_trace_get_environment_field_value_by_name(
+ struct bt_ctf_trace *trace, const char *name)
+{
+ return bt_ctf_object_get_ref(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_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_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_ctf_object_get_ref(bt_ctf_trace_common_borrow_clock_class_by_index(
+ BT_CTF_TO_COMMON(trace), index));
+}
+
+static
+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_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.");
+ }
+
+ return ret;
+}
+
+int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
+ struct bt_ctf_stream_class *stream_class)
+{
+ int ret = 0;
+ struct bt_ctf_clock_class *expected_clock_class = NULL;
+
+ if (!trace) {
+ BT_LOGW_STR("Invalid parameter: trace is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!stream_class) {
+ BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->clock) {
+ struct bt_ctf_clock_class *stream_clock_class =
+ stream_class->clock->clock_class;
+
+ /*
+ * Make sure this clock was also added to the
+ * trace (potentially through its CTF writer
+ * owner).
+ */
+ size_t i;
+
+ for (i = 0; i < trace->common.clock_classes->len; i++) {
+ if (trace->common.clock_classes->pdata[i] ==
+ stream_clock_class) {
+ /* Found! */
+ break;
+ }
+ }
+
+ if (i == trace->common.clock_classes->len) {
+ /* Not found */
+ BT_LOGW("Stream class's clock's class is not part of the trace: "
+ "clock-class-addr=%p, clock-class-name=\"%s\"",
+ stream_clock_class,
+ bt_ctf_clock_class_get_name(stream_clock_class));
+ ret = -1;
+ goto end;
+ }
+
+ if (stream_class->common.clock_class &&
+ stream_class->common.clock_class !=
+ stream_class->clock->clock_class) {
+ /*
+ * Stream class already has an expected clock
+ * class, but it does not match its clock's
+ * class.
+ */
+ BT_LOGW("Invalid parameter: stream class's clock's "
+ "class does not match stream class's "
+ "expected clock class: "
+ "stream-class-addr=%p, "
+ "stream-class-id=%" PRId64 ", "
+ "stream-class-name=\"%s\", "
+ "expected-clock-class-addr=%p, "
+ "expected-clock-class-name=\"%s\"",
+ stream_class,
+ bt_ctf_stream_class_get_id(stream_class),
+ bt_ctf_stream_class_get_name(stream_class),
+ 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 = stream_class->clock->clock_class;
+ }
+ }
+
+
+ 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);
+
+end:
+ return ret;
+}
+
+int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *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_ctf_object_get_ref(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_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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(
+ bt_ctf_trace_common_borrow_clock_class_by_name(BT_CTF_TO_COMMON(trace),
+ name));
+}
+
+static
+int append_trace_metadata(struct bt_ctf_trace *trace,
+ struct metadata_context *context)
+{
+ unsigned char *uuid = trace->common.uuid;
+ int ret = 0;
+
+ if (trace->common.native_byte_order == BT_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\"",
+ trace, bt_ctf_trace_get_name(trace));
+ ret = -1;
+ goto end;
+ }
+
+ g_string_append(context->string, "trace {\n");
+ g_string_append(context->string, "\tmajor = 1;\n");
+ g_string_append(context->string, "\tminor = 8;\n");
+ BT_ASSERT(trace->common.native_byte_order == BT_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,
+ "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ }
+
+ g_string_append_printf(context->string, "\tbyte_order = %s;\n",
+ 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 := ");
+ context->current_indentation_level++;
+ g_string_assign(context->field_name, "");
+ BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
+ ret = bt_ctf_field_type_serialize_recursive(
+ (void *) trace->common.packet_header_field_type,
+ context);
+ if (ret) {
+ goto end;
+ }
+ context->current_indentation_level--;
+ }
+
+ g_string_append(context->string, ";\n};\n\n");
+end:
+ return ret;
+}
+
+static
+void append_env_metadata(struct bt_ctf_trace *trace,
+ struct metadata_context *context)
+{
+ int64_t i;
+ int64_t env_size;
+
+ env_size = bt_ctf_attributes_get_count(trace->common.environment);
+ if (env_size <= 0) {
+ return;
+ }
+
+ g_string_append(context->string, "env {\n");
+
+ for (i = 0; i < env_size; i++) {
+ struct bt_ctf_private_value *env_field_value_obj = NULL;
+ const char *entry_name;
+
+ entry_name = bt_ctf_attributes_get_field_name(
+ trace->common.environment, i);
+ env_field_value_obj = bt_ctf_attributes_borrow_field_value(
+ trace->common.environment, i);
+
+ BT_ASSERT(entry_name);
+ BT_ASSERT(env_field_value_obj);
+
+ switch (bt_ctf_value_get_type(
+ bt_ctf_private_value_as_value(env_field_value_obj))) {
+ case BT_CTF_VALUE_TYPE_INTEGER:
+ {
+ int64_t int_value;
+
+ int_value = bt_ctf_value_integer_get(
+ bt_ctf_private_value_as_value(
+ env_field_value_obj));
+ g_string_append_printf(context->string,
+ "\t%s = %" PRId64 ";\n", entry_name,
+ int_value);
+ break;
+ }
+ case BT_CTF_VALUE_TYPE_STRING:
+ {
+ const char *str_value;
+ char *escaped_str = NULL;
+
+ str_value = bt_ctf_value_string_get(
+ bt_ctf_private_value_as_value(
+ env_field_value_obj));
+ escaped_str = g_strescape(str_value, NULL);
+ if (!escaped_str) {
+ BT_LOGE("Cannot escape string: string=\"%s\"",
+ str_value);
+ continue;
+ }
+
+ g_string_append_printf(context->string,
+ "\t%s = \"%s\";\n", entry_name, escaped_str);
+ free(escaped_str);
+ break;
+ }
+ default:
+ continue;
+ }
+ }
+
+ g_string_append(context->string, "};\n\n");
+}
+
+char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
+{
+ char *metadata = NULL;
+ struct metadata_context *context = NULL;
+ int err = 0;
+ size_t i;
+
+ if (!trace) {
+ BT_LOGW_STR("Invalid parameter: trace is NULL.");
+ goto end;
+ }
+
+ context = g_new0(struct metadata_context, 1);
+ if (!context) {
+ BT_LOGE_STR("Failed to allocate one metadata context.");
+ goto end;
+ }
+
+ context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
+ context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
+ g_string_append(context->string, "/* CTF 1.8 */\n\n");
+ if (append_trace_metadata(trace, context)) {
+ /* append_trace_metadata() logs errors */
+ goto error;
+ }
+ append_env_metadata(trace, context);
+ g_ptr_array_foreach(trace->common.clock_classes,
+ (GFunc) bt_ctf_clock_class_serialize, context);
+
+ for (i = 0; i < trace->common.stream_classes->len; i++) {
+ /* bt_ctf_stream_class_serialize() logs details */
+ err = bt_ctf_stream_class_serialize(
+ trace->common.stream_classes->pdata[i], context);
+ if (err) {
+ /* bt_ctf_stream_class_serialize() logs errors */
+ goto error;
+ }
+ }
+
+ metadata = context->string->str;
+
+error:
+ g_string_free(context->string, err ? TRUE : FALSE);
+ g_string_free(context->field_name, TRUE);
+ g_free(context);
+
+end:
+ return metadata;
+}
+
+enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
+ struct bt_ctf_trace *trace)
+{
+ return (int) bt_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_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_ctf_object_get_ref(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_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_ctf_trace_common_get_name(BT_CTF_TO_COMMON(trace));
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/ctf-writer/clock-class-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/utils.h>
+#include <babeltrace2/ctf-writer/object.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;
+}
--- /dev/null
+/*
+ * 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 "logging.h"
+
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+#include <babeltrace2/babeltrace-internal.h>
+#include <babeltrace2/ctf-writer/event-class-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/resolve-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/validation-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/ctf-writer/values-internal.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_ctf_private_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_ctf_private_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_ctf_private_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_ctf_private_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_ctf_object_get_ref(packet_header_type);
+ bt_ctf_object_get_ref(packet_context_type);
+ bt_ctf_object_get_ref(event_header_type);
+ bt_ctf_object_get_ref(stream_event_ctx_type);
+ bt_ctf_object_get_ref(event_context_type);
+ bt_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(packet_context_type, packet_context_type_copy);
+ BT_CTF_OBJECT_MOVE_REF(event_header_type, event_header_type_copy);
+ BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(event_context_type, event_context_type_copy);
+ BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_MOVE_REF(output->packet_header_type, packet_header_type);
+ BT_CTF_OBJECT_MOVE_REF(output->packet_context_type, packet_context_type);
+ BT_CTF_OBJECT_MOVE_REF(output->event_header_type, event_header_type);
+ BT_CTF_OBJECT_MOVE_REF(output->stream_event_ctx_type, stream_event_ctx_type);
+ BT_CTF_OBJECT_MOVE_REF(output->event_context_type, event_context_type);
+ BT_CTF_OBJECT_MOVE_REF(output->event_payload_type, event_payload_type);
+ return ret;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_MOVE_REF(stream_class->packet_context_field_type,
+ output->packet_context_type);
+ BT_CTF_OBJECT_MOVE_REF(stream_class->event_header_field_type,
+ output->event_header_type);
+ BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_MOVE_REF(event_class->context_field_type, output->event_context_type);
+ BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_header_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_context_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_header_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(output->stream_event_ctx_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_context_type);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_payload_type);
+}
--- /dev/null
+/*
+ * 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-VALUES"
+#include "logging.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <string.h>
+#include <inttypes.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/common-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <babeltrace2/ctf-writer/values-internal.h>
+#include <babeltrace2/compat/glib-internal.h>
+#include <babeltrace2/types.h>
+#include <babeltrace2/ctf-writer/object-internal.h>
+#include <babeltrace2/ctf-writer/values-internal.h>
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
+
+#define BT_CTF_VALUE_FROM_CONCRETE(_concrete) ((struct bt_ctf_value *) (_concrete))
+#define BT_CTF_VALUE_TO_BOOL(_base) ((struct bt_ctf_value_bool *) (_base))
+#define BT_CTF_VALUE_TO_INTEGER(_base) ((struct bt_ctf_value_integer *) (_base))
+#define BT_CTF_VALUE_TO_REAL(_base) ((struct bt_ctf_value_real *) (_base))
+#define BT_CTF_VALUE_TO_STRING(_base) ((struct bt_ctf_value_string *) (_base))
+#define BT_CTF_VALUE_TO_ARRAY(_base) ((struct bt_ctf_value_array *) (_base))
+#define BT_CTF_VALUE_TO_MAP(_base) ((struct bt_ctf_value_map *) (_base))
+
+#define BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(_value, _type) \
+ BT_CTF_ASSERT_PRE(((struct bt_ctf_value *) (_value))->type == (_type), \
+ "Value has the wrong type ID: expected-type=%d", (_type))
+
+#define BT_CTF_ASSERT_PRE_VALUE_HOT(_value, _name) \
+ BT_CTF_ASSERT_PRE_HOT(((struct bt_ctf_value *) (_value)), (_name), "")
+
+#define BT_CTF_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(_index, _count) \
+ BT_CTF_ASSERT_PRE((_index) < (_count), \
+ "Index is out of bound: " \
+ "index=%" PRIu64 ", count=%u", (_index), (_count));
+
+struct bt_ctf_value {
+ struct bt_ctf_object base;
+ enum bt_ctf_value_type type;
+ bt_bool frozen;
+};
+
+static
+void bt_ctf_value_null_instance_release_func(struct bt_ctf_object *obj)
+{
+ BT_LOGW("Releasing the null value singleton: addr=%p", obj);
+}
+
+static
+struct bt_ctf_value bt_ctf_value_null_instance = {
+ .base = {
+ .is_shared = true,
+ .ref_count = 1,
+ .release_func = bt_ctf_value_null_instance_release_func,
+ .spec_release_func = NULL,
+ .parent_is_owner_listener_func = NULL,
+ .parent = NULL,
+ },
+ .type = BT_CTF_VALUE_TYPE_NULL,
+ .frozen = BT_TRUE,
+};
+
+struct bt_ctf_value *const bt_ctf_value_null = &bt_ctf_value_null_instance;
+struct bt_ctf_private_value *const bt_ctf_private_value_null =
+ (void *) &bt_ctf_value_null_instance;
+
+struct bt_ctf_value_bool {
+ struct bt_ctf_value base;
+ bt_bool value;
+};
+
+struct bt_ctf_value_integer {
+ struct bt_ctf_value base;
+ int64_t value;
+};
+
+struct bt_ctf_value_real {
+ struct bt_ctf_value base;
+ double value;
+};
+
+struct bt_ctf_value_string {
+ struct bt_ctf_value base;
+ GString *gstr;
+};
+
+struct bt_ctf_value_array {
+ struct bt_ctf_value base;
+ GPtrArray *garray;
+};
+
+struct bt_ctf_value_map {
+ struct bt_ctf_value base;
+ GHashTable *ght;
+};
+
+static
+void bt_ctf_value_destroy(struct bt_ctf_object *obj);
+
+static
+void bt_ctf_value_string_destroy(struct bt_ctf_value *object)
+{
+ g_string_free(BT_CTF_VALUE_TO_STRING(object)->gstr, TRUE);
+ BT_CTF_VALUE_TO_STRING(object)->gstr = NULL;
+}
+
+static
+void bt_ctf_value_array_destroy(struct bt_ctf_value *object)
+{
+ /*
+ * Pointer array's registered value destructor will take care
+ * of putting each contained object.
+ */
+ g_ptr_array_free(BT_CTF_VALUE_TO_ARRAY(object)->garray, TRUE);
+ BT_CTF_VALUE_TO_ARRAY(object)->garray = NULL;
+}
+
+static
+void bt_ctf_value_map_destroy(struct bt_ctf_value *object)
+{
+ /*
+ * Hash table's registered value destructor will take care of
+ * putting each contained object. Keys are GQuarks and cannot
+ * be destroyed anyway.
+ */
+ g_hash_table_destroy(BT_CTF_VALUE_TO_MAP(object)->ght);
+ BT_CTF_VALUE_TO_MAP(object)->ght = NULL;
+}
+
+static
+void (* const destroy_funcs[])(struct bt_ctf_value *) = {
+ [BT_CTF_VALUE_TYPE_NULL] = NULL,
+ [BT_CTF_VALUE_TYPE_BOOL] = NULL,
+ [BT_CTF_VALUE_TYPE_INTEGER] = NULL,
+ [BT_CTF_VALUE_TYPE_REAL] = NULL,
+ [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_destroy,
+ [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_destroy,
+ [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_destroy,
+};
+
+static
+struct bt_ctf_private_value *bt_ctf_value_null_copy(const struct bt_ctf_value *null_obj)
+{
+ return (void *) bt_ctf_value_null;
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_bool_copy(const struct bt_ctf_value *bool_obj)
+{
+ return bt_ctf_private_value_bool_create_init(
+ BT_CTF_VALUE_TO_BOOL(bool_obj)->value);
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_integer_copy(
+ const struct bt_ctf_value *integer_obj)
+{
+ return bt_ctf_private_value_integer_create_init(
+ BT_CTF_VALUE_TO_INTEGER(integer_obj)->value);
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_real_copy(const struct bt_ctf_value *real_obj)
+{
+ return bt_ctf_private_value_real_create_init(
+ BT_CTF_VALUE_TO_REAL(real_obj)->value);
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_string_copy(const struct bt_ctf_value *string_obj)
+{
+ return bt_ctf_private_value_string_create_init(
+ BT_CTF_VALUE_TO_STRING(string_obj)->gstr->str);
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_array_copy(const struct bt_ctf_value *array_obj)
+{
+ int i;
+ int ret;
+ struct bt_ctf_private_value *copy_obj;
+ struct bt_ctf_value_array *typed_array_obj;
+
+ BT_LOGD("Copying array value: addr=%p", array_obj);
+ typed_array_obj = BT_CTF_VALUE_TO_ARRAY(array_obj);
+ copy_obj = bt_ctf_private_value_array_create();
+ if (!copy_obj) {
+ BT_LOGE_STR("Cannot create empty array value.");
+ goto end;
+ }
+
+ for (i = 0; i < typed_array_obj->garray->len; ++i) {
+ struct bt_ctf_private_value *element_obj_copy = NULL;
+ struct bt_ctf_value *element_obj =
+ bt_ctf_value_array_borrow_element_by_index(
+ array_obj, i);
+
+ BT_ASSERT(element_obj);
+ BT_LOGD("Copying array value's element: element-addr=%p, "
+ "index=%d", element_obj, i);
+ ret = bt_ctf_value_copy(&element_obj_copy, element_obj);
+ if (ret) {
+ BT_LOGE("Cannot copy array value's element: "
+ "array-addr=%p, index=%d",
+ array_obj, i);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
+ goto end;
+ }
+
+ BT_ASSERT(element_obj_copy);
+ ret = bt_ctf_private_value_array_append_element(copy_obj,
+ (void *) element_obj_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
+ if (ret) {
+ BT_LOGE("Cannot append to array value: addr=%p",
+ array_obj);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
+ goto end;
+ }
+ }
+
+ BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
+ array_obj, copy_obj);
+
+end:
+ return copy_obj;
+}
+
+static
+struct bt_ctf_private_value *bt_ctf_value_map_copy(const struct bt_ctf_value *map_obj)
+{
+ int ret;
+ GHashTableIter iter;
+ gpointer key, element_obj;
+ struct bt_ctf_private_value *copy_obj;
+ struct bt_ctf_private_value *element_obj_copy = NULL;
+ struct bt_ctf_value_map *typed_map_obj;
+
+ BT_LOGD("Copying map value: addr=%p", map_obj);
+ typed_map_obj = BT_CTF_VALUE_TO_MAP(map_obj);
+ copy_obj = bt_ctf_private_value_map_create();
+ if (!copy_obj) {
+ goto end;
+ }
+
+ g_hash_table_iter_init(&iter, typed_map_obj->ght);
+
+ while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+ const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
+
+ BT_ASSERT(key_str);
+ BT_LOGD("Copying map value's element: element-addr=%p, "
+ "key=\"%s\"", element_obj, key_str);
+ ret = bt_ctf_value_copy(&element_obj_copy, element_obj);
+ if (ret) {
+ BT_LOGE("Cannot copy map value's element: "
+ "map-addr=%p, key=\"%s\"",
+ map_obj, key_str);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
+ goto end;
+ }
+
+ BT_ASSERT(element_obj_copy);
+ ret = bt_ctf_private_value_map_insert_entry(copy_obj, key_str,
+ (void *) element_obj_copy);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
+ if (ret) {
+ BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
+ map_obj, key_str);
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
+ goto end;
+ }
+ }
+
+ BT_LOGD("Copied map value: addr=%p", map_obj);
+
+end:
+ return copy_obj;
+}
+
+static
+struct bt_ctf_private_value *(* const copy_funcs[])(const struct bt_ctf_value *) = {
+ [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_copy,
+ [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_bool_copy,
+ [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_integer_copy,
+ [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_real_copy,
+ [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_copy,
+ [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_copy,
+ [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_copy,
+};
+
+static
+bt_bool bt_ctf_value_null_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ /*
+ * Always BT_TRUE since bt_ctf_value_compare() already checks if both
+ * object_a and object_b have the same type, and in the case of
+ * null value objects, they're always the same if it is so.
+ */
+ return BT_TRUE;
+}
+
+static
+bt_bool bt_ctf_value_bool_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ if (BT_CTF_VALUE_TO_BOOL(object_a)->value !=
+ BT_CTF_VALUE_TO_BOOL(object_b)->value) {
+ BT_LOGV("Boolean value objects are different: "
+ "bool-a-val=%d, bool-b-val=%d",
+ BT_CTF_VALUE_TO_BOOL(object_a)->value,
+ BT_CTF_VALUE_TO_BOOL(object_b)->value);
+ return BT_FALSE;
+ }
+
+ return BT_TRUE;
+}
+
+static
+bt_bool bt_ctf_value_integer_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ if (BT_CTF_VALUE_TO_INTEGER(object_a)->value !=
+ BT_CTF_VALUE_TO_INTEGER(object_b)->value) {
+ BT_LOGV("Integer value objects are different: "
+ "int-a-val=%" PRId64 ", int-b-val=%" PRId64,
+ BT_CTF_VALUE_TO_INTEGER(object_a)->value,
+ BT_CTF_VALUE_TO_INTEGER(object_b)->value);
+ return BT_FALSE;
+ }
+
+ return BT_TRUE;
+}
+
+static
+bt_bool bt_ctf_value_real_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ if (BT_CTF_VALUE_TO_REAL(object_a)->value !=
+ BT_CTF_VALUE_TO_REAL(object_b)->value) {
+ BT_LOGV("Real number value objects are different: "
+ "real-a-val=%f, real-b-val=%f",
+ BT_CTF_VALUE_TO_REAL(object_a)->value,
+ BT_CTF_VALUE_TO_REAL(object_b)->value);
+ return BT_FALSE;
+ }
+
+ return BT_TRUE;
+}
+
+static
+bt_bool bt_ctf_value_string_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ if (strcmp(BT_CTF_VALUE_TO_STRING(object_a)->gstr->str,
+ BT_CTF_VALUE_TO_STRING(object_b)->gstr->str) != 0) {
+ BT_LOGV("String value objects are different: "
+ "string-a-val=\"%s\", string-b-val=\"%s\"",
+ BT_CTF_VALUE_TO_STRING(object_a)->gstr->str,
+ BT_CTF_VALUE_TO_STRING(object_b)->gstr->str);
+ return BT_FALSE;
+ }
+
+ return BT_TRUE;
+}
+
+static
+bt_bool bt_ctf_value_array_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ int i;
+ bt_bool ret = BT_TRUE;
+ const struct bt_ctf_value_array *array_obj_a =
+ BT_CTF_VALUE_TO_ARRAY(object_a);
+
+ if (bt_ctf_value_array_get_size(object_a) !=
+ bt_ctf_value_array_get_size(object_b)) {
+ BT_LOGV("Array values are different: size mismatch "
+ "value-a-addr=%p, value-b-addr=%p, "
+ "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
+ object_a, object_b,
+ bt_ctf_value_array_get_size(object_a),
+ bt_ctf_value_array_get_size(object_b));
+ ret = BT_FALSE;
+ goto end;
+ }
+
+ for (i = 0; i < array_obj_a->garray->len; ++i) {
+ struct bt_ctf_value *element_obj_a;
+ struct bt_ctf_value *element_obj_b;
+
+ element_obj_a = bt_ctf_value_array_borrow_element_by_index(
+ object_a, i);
+ element_obj_b = bt_ctf_value_array_borrow_element_by_index(
+ object_b, i);
+
+ if (!bt_ctf_value_compare(element_obj_a, element_obj_b)) {
+ BT_LOGV("Array values's elements are different: "
+ "value-a-addr=%p, value-b-addr=%p, index=%d",
+ element_obj_a, element_obj_b, i);
+ ret = BT_FALSE;
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+bt_bool bt_ctf_value_map_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ bt_bool ret = BT_TRUE;
+ GHashTableIter iter;
+ gpointer key, element_obj_a;
+ const struct bt_ctf_value_map *map_obj_a = BT_CTF_VALUE_TO_MAP(object_a);
+
+ if (bt_ctf_value_map_get_size(object_a) !=
+ bt_ctf_value_map_get_size(object_b)) {
+ BT_LOGV("Map values are different: size mismatch "
+ "value-a-addr=%p, value-b-addr=%p, "
+ "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
+ object_a, object_b,
+ bt_ctf_value_map_get_size(object_a),
+ bt_ctf_value_map_get_size(object_b));
+ ret = BT_FALSE;
+ goto end;
+ }
+
+ g_hash_table_iter_init(&iter, map_obj_a->ght);
+
+ while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
+ struct bt_ctf_value *element_obj_b;
+ const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
+
+ element_obj_b = bt_ctf_value_map_borrow_entry_value(object_b,
+ key_str);
+
+ if (!bt_ctf_value_compare(element_obj_a, element_obj_b)) {
+ BT_LOGV("Map values's elements are different: "
+ "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
+ element_obj_a, element_obj_b, key_str);
+ ret = BT_FALSE;
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static
+bt_bool (* const compare_funcs[])(const struct bt_ctf_value *,
+ const struct bt_ctf_value *) = {
+ [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_compare,
+ [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_bool_compare,
+ [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_integer_compare,
+ [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_real_compare,
+ [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_compare,
+ [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_compare,
+ [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_compare,
+};
+
+static
+void bt_ctf_value_null_freeze(struct bt_ctf_value *object)
+{
+}
+
+static
+void bt_ctf_value_generic_freeze(struct bt_ctf_value *object)
+{
+ object->frozen = BT_TRUE;
+}
+
+static
+void bt_ctf_value_array_freeze(struct bt_ctf_value *object)
+{
+ int i;
+ struct bt_ctf_value_array *typed_array_obj =
+ BT_CTF_VALUE_TO_ARRAY(object);
+
+ for (i = 0; i < typed_array_obj->garray->len; ++i) {
+ bt_ctf_value_freeze(g_ptr_array_index(typed_array_obj->garray, i));
+ }
+
+ bt_ctf_value_generic_freeze(object);
+}
+
+static
+void bt_ctf_value_map_freeze(struct bt_ctf_value *object)
+{
+ GHashTableIter iter;
+ gpointer key, element_obj;
+ const struct bt_ctf_value_map *map_obj = BT_CTF_VALUE_TO_MAP(object);
+
+ g_hash_table_iter_init(&iter, map_obj->ght);
+
+ while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+ bt_ctf_value_freeze(element_obj);
+ }
+
+ bt_ctf_value_generic_freeze(object);
+}
+
+static
+void (* const freeze_funcs[])(struct bt_ctf_value *) = {
+ [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_freeze,
+ [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_generic_freeze,
+ [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_generic_freeze,
+ [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_generic_freeze,
+ [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_generic_freeze,
+ [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_freeze,
+ [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_freeze,
+};
+
+static
+void bt_ctf_value_destroy(struct bt_ctf_object *obj)
+{
+ struct bt_ctf_value *value;
+
+ value = container_of(obj, struct bt_ctf_value, base);
+ BT_LOGD("Destroying value: addr=%p", value);
+
+ if (bt_ctf_value_is_null(value)) {
+ BT_LOGD_STR("Not destroying the null value singleton.");
+ return;
+ }
+
+ if (destroy_funcs[value->type]) {
+ destroy_funcs[value->type](value);
+ }
+
+ g_free(value);
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status _bt_ctf_value_freeze(struct bt_ctf_value *object)
+{
+ enum bt_ctf_value_status ret = BT_CTF_VALUE_STATUS_OK;
+
+ BT_ASSERT(object);
+
+ if (object->frozen) {
+ goto end;
+ }
+
+ BT_LOGD("Freezing value: addr=%p", object);
+ freeze_funcs[object->type](object);
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_type bt_ctf_value_get_type(const struct bt_ctf_value *object)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(object, "Value object");
+ return object->type;
+}
+
+static
+struct bt_ctf_value bt_ctf_value_create_base(enum bt_ctf_value_type type)
+{
+ struct bt_ctf_value value;
+
+ value.type = type;
+ value.frozen = BT_FALSE;
+ bt_ctf_object_init_shared(&value.base, bt_ctf_value_destroy);
+ return value;
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_bool_create_init(bt_bool val)
+{
+ struct bt_ctf_value_bool *bool_obj;
+
+ BT_LOGD("Creating boolean value object: val=%d", val);
+ bool_obj = g_new0(struct bt_ctf_value_bool, 1);
+ if (!bool_obj) {
+ BT_LOGE_STR("Failed to allocate one boolean value object.");
+ goto end;
+ }
+
+ bool_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_BOOL);
+ bool_obj->value = val;
+ BT_LOGD("Created boolean value object: addr=%p", bool_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(bool_obj);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_bool_create(void)
+{
+ return bt_ctf_private_value_bool_create_init(BT_FALSE);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_integer_create_init(int64_t val)
+{
+ struct bt_ctf_value_integer *integer_obj;
+
+ BT_LOGD("Creating integer value object: val=%" PRId64, val);
+ integer_obj = g_new0(struct bt_ctf_value_integer, 1);
+ if (!integer_obj) {
+ BT_LOGE_STR("Failed to allocate one integer value object.");
+ goto end;
+ }
+
+ integer_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_INTEGER);
+ integer_obj->value = val;
+ BT_LOGD("Created integer value object: addr=%p",
+ integer_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(integer_obj);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_integer_create(void)
+{
+ return bt_ctf_private_value_integer_create_init(0);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_real_create_init(double val)
+{
+ struct bt_ctf_value_real *real_obj;
+
+ BT_LOGD("Creating real number value object: val=%f", val);
+ real_obj = g_new0(struct bt_ctf_value_real, 1);
+ if (!real_obj) {
+ BT_LOGE_STR("Failed to allocate one real number value object.");
+ goto end;
+ }
+
+ real_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_REAL);
+ real_obj->value = val;
+ BT_LOGD("Created real number value object: addr=%p",
+ real_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(real_obj);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_real_create(void)
+{
+ return bt_ctf_private_value_real_create_init(0.);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_string_create_init(const char *val)
+{
+ struct bt_ctf_value_string *string_obj = NULL;
+
+ if (!val) {
+ BT_LOGW_STR("Invalid parameter: value is NULL.");
+ goto end;
+ }
+
+ BT_LOGD("Creating string value object: val-len=%zu", strlen(val));
+ string_obj = g_new0(struct bt_ctf_value_string, 1);
+ if (!string_obj) {
+ BT_LOGE_STR("Failed to allocate one string object.");
+ goto end;
+ }
+
+ string_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_STRING);
+ string_obj->gstr = g_string_new(val);
+ if (!string_obj->gstr) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ g_free(string_obj);
+ string_obj = NULL;
+ goto end;
+ }
+
+ BT_LOGD("Created string value object: addr=%p",
+ string_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(string_obj);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_string_create(void)
+{
+ return bt_ctf_private_value_string_create_init("");
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_array_create(void)
+{
+ struct bt_ctf_value_array *array_obj;
+
+ BT_LOGD_STR("Creating empty array value object.");
+ array_obj = g_new0(struct bt_ctf_value_array, 1);
+ if (!array_obj) {
+ BT_LOGE_STR("Failed to allocate one array object.");
+ goto end;
+ }
+
+ array_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_ARRAY);
+ array_obj->garray = bt_g_ptr_array_new_full(0,
+ (GDestroyNotify) bt_ctf_object_put_ref);
+ if (!array_obj->garray) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ g_free(array_obj);
+ array_obj = NULL;
+ goto end;
+ }
+
+ BT_LOGD("Created array value object: addr=%p",
+ array_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(array_obj);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_map_create(void)
+{
+ struct bt_ctf_value_map *map_obj;
+
+ BT_LOGD_STR("Creating empty map value object.");
+ map_obj = g_new0(struct bt_ctf_value_map, 1);
+ if (!map_obj) {
+ BT_LOGE_STR("Failed to allocate one map object.");
+ goto end;
+ }
+
+ map_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_MAP);
+ map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) bt_ctf_object_put_ref);
+ if (!map_obj->ght) {
+ BT_LOGE_STR("Failed to allocate a GHashTable.");
+ g_free(map_obj);
+ map_obj = NULL;
+ goto end;
+ }
+
+ BT_LOGD("Created map value object: addr=%p",
+ map_obj);
+
+end:
+ return (void *) BT_CTF_VALUE_FROM_CONCRETE(map_obj);
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_value_bool_get(const struct bt_ctf_value *bool_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_CTF_VALUE_TYPE_BOOL);
+ return BT_CTF_VALUE_TO_BOOL(bool_obj)->value;
+}
+
+BT_HIDDEN
+void bt_ctf_private_value_bool_set(struct bt_ctf_private_value *bool_obj, bt_bool val)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_CTF_VALUE_TYPE_BOOL);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(bool_obj, "Value object");
+ BT_CTF_VALUE_TO_BOOL(bool_obj)->value = val;
+ BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
+ bool_obj, val);
+}
+
+BT_HIDDEN
+int64_t bt_ctf_value_integer_get(const struct bt_ctf_value *integer_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_CTF_VALUE_TYPE_INTEGER);
+ return BT_CTF_VALUE_TO_INTEGER(integer_obj)->value;
+}
+
+BT_HIDDEN
+void bt_ctf_private_value_integer_set(struct bt_ctf_private_value *integer_obj,
+ int64_t val)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_CTF_VALUE_TYPE_INTEGER);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(integer_obj, "Value object");
+ BT_CTF_VALUE_TO_INTEGER(integer_obj)->value = val;
+ BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
+ integer_obj, val);
+}
+
+BT_HIDDEN
+double bt_ctf_value_real_get(const struct bt_ctf_value *real_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(real_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_CTF_VALUE_TYPE_REAL);
+ return BT_CTF_VALUE_TO_REAL(real_obj)->value;
+}
+
+BT_HIDDEN
+void bt_ctf_private_value_real_set(struct bt_ctf_private_value *real_obj, double val)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(real_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_CTF_VALUE_TYPE_REAL);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(real_obj, "Value object");
+ BT_CTF_VALUE_TO_REAL(real_obj)->value = val;
+ BT_LOGV("Set real number value's raw value: value-addr=%p, value=%f",
+ real_obj, val);
+}
+
+BT_HIDDEN
+const char *bt_ctf_value_string_get(const struct bt_ctf_value *string_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(string_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_CTF_VALUE_TYPE_STRING);
+ return BT_CTF_VALUE_TO_STRING(string_obj)->gstr->str;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_string_set(
+ struct bt_ctf_private_value *string_obj, const char *val)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(string_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_CTF_VALUE_TYPE_STRING);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(string_obj, "Value object");
+ g_string_assign(BT_CTF_VALUE_TO_STRING(string_obj)->gstr, val);
+ BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
+ string_obj, val);
+ return BT_CTF_VALUE_STATUS_OK;
+}
+
+BT_HIDDEN
+uint64_t bt_ctf_value_array_get_size(const struct bt_ctf_value *array_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(array_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
+ return (uint64_t) BT_CTF_VALUE_TO_ARRAY(array_obj)->garray->len;
+}
+
+BT_HIDDEN
+struct bt_ctf_value *bt_ctf_value_array_borrow_element_by_index(
+ const struct bt_ctf_value *array_obj,
+ uint64_t index)
+{
+ struct bt_ctf_value_array *typed_array_obj =
+ BT_CTF_VALUE_TO_ARRAY(array_obj);
+
+ BT_CTF_ASSERT_PRE_NON_NULL(array_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
+ BT_CTF_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
+ typed_array_obj->garray->len);
+ return g_ptr_array_index(typed_array_obj->garray, index);
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_array_borrow_element_by_index(
+ const struct bt_ctf_private_value *array_obj,
+ uint64_t index)
+{
+ return (void *) bt_ctf_value_array_borrow_element_by_index(
+ (void *) array_obj, index);
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_element(
+ struct bt_ctf_private_value *array_obj,
+ struct bt_ctf_value *element_obj)
+{
+ struct bt_ctf_value_array *typed_array_obj =
+ BT_CTF_VALUE_TO_ARRAY(array_obj);
+
+ BT_CTF_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
+ g_ptr_array_add(typed_array_obj->garray, element_obj);
+ bt_ctf_object_get_ref(element_obj);
+ BT_LOGV("Appended element to array value: array-value-addr=%p, "
+ "element-value-addr=%p, new-size=%u",
+ array_obj, element_obj, typed_array_obj->garray->len);
+ return BT_CTF_VALUE_STATUS_OK;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_bool_element(
+ struct bt_ctf_private_value *array_obj, bt_bool val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *bool_obj = NULL;
+
+ bool_obj = bt_ctf_private_value_bool_create_init(val);
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) bool_obj);
+ bt_ctf_object_put_ref(bool_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_integer_element(
+ struct bt_ctf_private_value *array_obj, int64_t val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *integer_obj = NULL;
+
+ integer_obj = bt_ctf_private_value_integer_create_init(val);
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) integer_obj);
+ bt_ctf_object_put_ref(integer_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_real_element(
+ struct bt_ctf_private_value *array_obj, double val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *real_obj = NULL;
+
+ real_obj = bt_ctf_private_value_real_create_init(val);
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) real_obj);
+ bt_ctf_object_put_ref(real_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_string_element(
+ struct bt_ctf_private_value *array_obj, const char *val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *string_obj = NULL;
+
+ string_obj = bt_ctf_private_value_string_create_init(val);
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) string_obj);
+ bt_ctf_object_put_ref(string_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_empty_array_element(
+ struct bt_ctf_private_value *array_obj)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *empty_array_obj = NULL;
+
+ empty_array_obj = bt_ctf_private_value_array_create();
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) empty_array_obj);
+ bt_ctf_object_put_ref(empty_array_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_append_empty_map_element(
+ struct bt_ctf_private_value *array_obj)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *map_obj = NULL;
+
+ map_obj = bt_ctf_private_value_map_create();
+ ret = bt_ctf_private_value_array_append_element(array_obj,
+ (void *) map_obj);
+ bt_ctf_object_put_ref(map_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_array_set_element_by_index(
+ struct bt_ctf_private_value *array_obj, uint64_t index,
+ struct bt_ctf_value *element_obj)
+{
+ struct bt_ctf_value_array *typed_array_obj =
+ BT_CTF_VALUE_TO_ARRAY(array_obj);
+
+ BT_CTF_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
+ BT_CTF_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
+ typed_array_obj->garray->len);
+ bt_ctf_object_put_ref(g_ptr_array_index(typed_array_obj->garray, index));
+ g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
+ bt_ctf_object_get_ref(element_obj);
+ BT_LOGV("Set array value's element: array-value-addr=%p, "
+ "index=%" PRIu64 ", element-value-addr=%p",
+ array_obj, index, element_obj);
+ return BT_CTF_VALUE_STATUS_OK;
+}
+
+BT_HIDDEN
+uint64_t bt_ctf_value_map_get_size(const struct bt_ctf_value *map_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(map_obj, "Value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
+ return (uint64_t) g_hash_table_size(BT_CTF_VALUE_TO_MAP(map_obj)->ght);
+}
+
+BT_HIDDEN
+struct bt_ctf_value *bt_ctf_value_map_borrow_entry_value(const struct bt_ctf_value *map_obj,
+ const char *key)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(map_obj, "Value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(key, "Key");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
+ return g_hash_table_lookup(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
+ GUINT_TO_POINTER(g_quark_from_string(key)));
+}
+
+BT_HIDDEN
+struct bt_ctf_private_value *bt_ctf_private_value_map_borrow_entry_value(
+ const struct bt_ctf_private_value *map_obj, const char *key)
+{
+ return (void *) bt_ctf_value_map_borrow_entry_value((void *) map_obj, key);
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_value_map_has_entry(const struct bt_ctf_value *map_obj, const char *key)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(map_obj, "Value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(key, "Key");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
+ return bt_g_hash_table_contains(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
+ GUINT_TO_POINTER(g_quark_from_string(key)));
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_entry(
+ struct bt_ctf_private_value *map_obj,
+ const char *key, struct bt_ctf_value *element_obj)
+{
+ BT_CTF_ASSERT_PRE_NON_NULL(map_obj, "Map value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(key, "Key");
+ BT_CTF_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
+ BT_CTF_ASSERT_PRE_VALUE_HOT(map_obj, "Map value object");
+ g_hash_table_insert(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
+ GUINT_TO_POINTER(g_quark_from_string(key)), element_obj);
+ bt_ctf_object_get_ref(element_obj);
+ BT_LOGV("Inserted value into map value: map-value-addr=%p, "
+ "key=\"%s\", element-value-addr=%p",
+ map_obj, key, element_obj);
+ return BT_CTF_VALUE_STATUS_OK;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_bool_entry(
+ struct bt_ctf_private_value *map_obj, const char *key, bt_bool val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *bool_obj = NULL;
+
+ bool_obj = bt_ctf_private_value_bool_create_init(val);
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) bool_obj);
+ bt_ctf_object_put_ref(bool_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_integer_entry(
+ struct bt_ctf_private_value *map_obj, const char *key, int64_t val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *integer_obj = NULL;
+
+ integer_obj = bt_ctf_private_value_integer_create_init(val);
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) integer_obj);
+ bt_ctf_object_put_ref(integer_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_real_entry(
+ struct bt_ctf_private_value *map_obj, const char *key, double val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *real_obj = NULL;
+
+ real_obj = bt_ctf_private_value_real_create_init(val);
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) real_obj);
+ bt_ctf_object_put_ref(real_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_string_entry(
+ struct bt_ctf_private_value *map_obj, const char *key,
+ const char *val)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *string_obj = NULL;
+
+ string_obj = bt_ctf_private_value_string_create_init(val);
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) string_obj);
+ bt_ctf_object_put_ref(string_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_empty_array_entry(
+ struct bt_ctf_private_value *map_obj, const char *key)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *array_obj = NULL;
+
+ array_obj = bt_ctf_private_value_array_create();
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) array_obj);
+ bt_ctf_object_put_ref(array_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_insert_empty_map_entry(
+ struct bt_ctf_private_value *map_obj, const char *key)
+{
+ enum bt_ctf_value_status ret;
+ struct bt_ctf_private_value *empty_map_obj = NULL;
+
+ empty_map_obj = bt_ctf_private_value_map_create();
+ ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
+ (void *) empty_map_obj);
+ bt_ctf_object_put_ref(empty_map_obj);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_value_map_foreach_entry(const struct bt_ctf_value *map_obj,
+ bt_ctf_value_map_foreach_entry_cb cb, void *data)
+{
+ enum bt_ctf_value_status ret = BT_CTF_VALUE_STATUS_OK;
+ gpointer key, element_obj;
+ GHashTableIter iter;
+ struct bt_ctf_value_map *typed_map_obj = BT_CTF_VALUE_TO_MAP(map_obj);
+
+ BT_CTF_ASSERT_PRE_NON_NULL(map_obj, "Value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(cb, "Callback");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
+ g_hash_table_iter_init(&iter, typed_map_obj->ght);
+
+ while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+ const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
+
+ if (!cb(key_str, element_obj, data)) {
+ BT_LOGV("User canceled the loop: key=\"%s\", "
+ "value-addr=%p, data=%p",
+ key_str, element_obj, data);
+ ret = BT_CTF_VALUE_STATUS_CANCELED;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_private_value_map_foreach_entry(
+ const struct bt_ctf_private_value *map_obj,
+ bt_ctf_private_value_map_foreach_entry_cb cb, void *data)
+{
+ return bt_ctf_value_map_foreach_entry((void *) map_obj,
+ (bt_ctf_value_map_foreach_entry_cb) cb, data);
+}
+
+struct extend_map_element_data {
+ struct bt_ctf_private_value *extended_obj;
+ enum bt_ctf_value_status status;
+};
+
+static
+bt_bool extend_map_element(const char *key,
+ struct bt_ctf_value *extension_obj_elem, void *data)
+{
+ bt_bool ret = BT_TRUE;
+ struct extend_map_element_data *extend_data = data;
+ struct bt_ctf_private_value *extension_obj_elem_copy = NULL;
+
+ /* Copy object which is to replace the current one */
+ extend_data->status = bt_ctf_value_copy(&extension_obj_elem_copy,
+ extension_obj_elem);
+ if (extend_data->status) {
+ BT_LOGE("Cannot copy map element: addr=%p",
+ extension_obj_elem);
+ goto error;
+ }
+
+ BT_ASSERT(extension_obj_elem_copy);
+
+ /* Replace in extended object */
+ extend_data->status = bt_ctf_private_value_map_insert_entry(
+ extend_data->extended_obj, key,
+ (void *) extension_obj_elem_copy);
+ if (extend_data->status) {
+ BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
+ "extended-value-addr=%p, element-value-addr=%p",
+ key, extend_data->extended_obj,
+ extension_obj_elem_copy);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_ASSERT(extend_data->status != BT_CTF_VALUE_STATUS_OK);
+ ret = BT_FALSE;
+
+end:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
+ return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_value_map_extend(
+ struct bt_ctf_private_value **extended_map_obj,
+ const struct bt_ctf_value *base_map_obj,
+ const struct bt_ctf_value *extension_obj)
+{
+ struct extend_map_element_data extend_data = {
+ .extended_obj = NULL,
+ .status = BT_CTF_VALUE_STATUS_OK,
+ };
+
+ BT_CTF_ASSERT_PRE_NON_NULL(base_map_obj, "Base value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(extension_obj, "Extension value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(extended_map_obj,
+ "Extended value object (output)");
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(base_map_obj, BT_CTF_VALUE_TYPE_MAP);
+ BT_CTF_ASSERT_PRE_VALUE_IS_TYPE(extension_obj, BT_CTF_VALUE_TYPE_MAP);
+ BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
+ base_map_obj, extension_obj);
+ *extended_map_obj = NULL;
+
+ /* Create copy of base map object to start with */
+ extend_data.status = bt_ctf_value_copy(extended_map_obj, base_map_obj);
+ if (extend_data.status) {
+ BT_LOGE("Cannot copy base value: base-value-addr=%p",
+ base_map_obj);
+ goto error;
+ }
+
+ BT_ASSERT(extended_map_obj);
+
+ /*
+ * For each key in the extension map object, replace this key
+ * in the copied map object.
+ */
+ extend_data.extended_obj = *extended_map_obj;
+
+ if (bt_ctf_value_map_foreach_entry(extension_obj, extend_map_element,
+ &extend_data)) {
+ BT_LOGE("Cannot iterate on the extension object's elements: "
+ "extension-value-addr=%p", extension_obj);
+ goto error;
+ }
+
+ if (extend_data.status) {
+ BT_LOGE("Failed to successfully iterate on the extension object's elements: "
+ "extension-value-addr=%p", extension_obj);
+ goto error;
+ }
+
+ BT_LOGD("Extended map value: extended-value-addr=%p",
+ *extended_map_obj);
+ goto end;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(*extended_map_obj);
+ *extended_map_obj = NULL;
+
+end:
+ return extend_data.status;
+}
+
+BT_HIDDEN
+enum bt_ctf_value_status bt_ctf_value_copy(struct bt_ctf_private_value **copy_obj,
+ const struct bt_ctf_value *object)
+{
+ enum bt_ctf_value_status status = BT_CTF_VALUE_STATUS_OK;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(object, "Value object");
+ BT_CTF_ASSERT_PRE_NON_NULL(copy_obj, "Value object copy (output)");
+ BT_LOGD("Copying value object: addr=%p", object);
+ *copy_obj = copy_funcs[object->type](object);
+ if (*copy_obj) {
+ BT_LOGD("Copied value object: copy-value-addr=%p",
+ copy_obj);
+ } else {
+ status = BT_CTF_VALUE_STATUS_NOMEM;
+ *copy_obj = NULL;
+ BT_LOGE_STR("Failed to copy value object.");
+ }
+
+ return status;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_value_compare(const struct bt_ctf_value *object_a,
+ const struct bt_ctf_value *object_b)
+{
+ bt_bool ret = BT_FALSE;
+
+ BT_CTF_ASSERT_PRE_NON_NULL(object_a, "Value object A");
+ BT_CTF_ASSERT_PRE_NON_NULL(object_b, "Value object B");
+
+ if (object_a->type != object_b->type) {
+ BT_LOGV("Values are different: type mismatch: "
+ "value-a-addr=%p, value-b-addr=%p, "
+ "value-a-type=%d, value-b-type=%d",
+ object_a, object_b, object_a->type, object_b->type);
+ goto end;
+ }
+
+ ret = compare_funcs[object_a->type](object_a, object_b);
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * 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 <babeltrace2/ctf-writer/visitor-internal.h>
+#include <babeltrace2/ctf-writer/object.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_CTF_OBJECT_PUT_REF_AND_RESET(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;
+}
--- /dev/null
+/*
+ * writer.c
+ *
+ * Babeltrace CTF Writer
+ *
+ * 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"
+#include "logging.h"
+
+#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/compat/uuid-internal.h>
+#include <babeltrace2/compiler-internal.h>
+#include <babeltrace2/ctf-writer/clock-internal.h>
+#include <babeltrace2/ctf-writer/field-types-internal.h>
+#include <babeltrace2/ctf-writer/fields-internal.h>
+#include <babeltrace2/ctf-writer/functor-internal.h>
+#include <babeltrace2/ctf-writer/stream-class-internal.h>
+#include <babeltrace2/ctf-writer/stream-internal.h>
+#include <babeltrace2/ctf-writer/trace-internal.h>
+#include <babeltrace2/ctf-writer/writer-internal.h>
+#include <babeltrace2/endian-internal.h>
+#include <babeltrace2/ctf-writer/object.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static
+void bt_ctf_writer_destroy(struct bt_ctf_object *obj);
+
+static
+int init_trace_packet_header(struct bt_ctf_trace *trace)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *_uint32_t =
+ get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
+ struct bt_ctf_field_type *_uint8_t =
+ get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
+ struct bt_ctf_field_type *trace_packet_header_type =
+ bt_ctf_field_type_structure_create();
+ struct bt_ctf_field_type *uuid_array_type =
+ bt_ctf_field_type_array_create(_uint8_t, 16);
+
+ if (!trace_packet_header_type || !uuid_array_type) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
+ _uint32_t, "magic");
+ if (ret) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
+ uuid_array_type, "uuid");
+ if (ret) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
+ _uint32_t, "stream_id");
+ if (ret) {
+ goto end;
+ }
+
+ ret = bt_ctf_trace_set_packet_header_field_type(trace,
+ trace_packet_header_type);
+ if (ret) {
+ goto end;
+ }
+end:
+ bt_ctf_object_put_ref(uuid_array_type);
+ bt_ctf_object_put_ref(_uint32_t);
+ bt_ctf_object_put_ref(_uint8_t);
+ bt_ctf_object_put_ref(trace_packet_header_type);
+ return ret;
+}
+
+struct bt_ctf_writer *bt_ctf_writer_create(const char *path)
+{
+ int ret;
+ struct bt_ctf_writer *writer = NULL;
+ unsigned char uuid[16];
+ char *metadata_path = NULL;
+
+ if (!path) {
+ goto error;
+ }
+
+ writer = g_new0(struct bt_ctf_writer, 1);
+ if (!writer) {
+ goto error;
+ }
+
+ metadata_path = g_build_filename(path, "metadata", NULL);
+
+ bt_ctf_object_init_shared(&writer->base, bt_ctf_writer_destroy);
+ writer->path = g_string_new(path);
+ if (!writer->path) {
+ goto error_destroy;
+ }
+
+ writer->trace = bt_ctf_trace_create();
+ if (!writer->trace) {
+ goto error_destroy;
+ }
+
+ ret = init_trace_packet_header(writer->trace);
+ if (ret) {
+ goto error_destroy;
+ }
+
+ /* Generate a UUID for this writer's trace */
+ ret = bt_uuid_generate(uuid);
+ if (ret) {
+ BT_LOGE_STR("Cannot generate UUID for CTF writer's trace.");
+ goto error_destroy;
+ }
+
+ ret = bt_ctf_trace_set_uuid(writer->trace, uuid);
+ if (ret) {
+ goto error_destroy;
+ }
+
+ bt_ctf_object_set_parent(&writer->trace->common.base, &writer->base);
+ bt_ctf_object_put_ref(writer->trace);
+
+ /* Default to little-endian */
+ ret = bt_ctf_writer_set_byte_order(writer, BT_CTF_BYTE_ORDER_NATIVE);
+ BT_ASSERT(ret == 0);
+
+ /* Create trace directory if necessary and open a metadata file */
+ if (g_mkdir_with_parents(path, S_IRWXU | S_IRWXG)) {
+ perror("g_mkdir_with_parents");
+ goto error_destroy;
+ }
+
+ writer->metadata_fd = open(metadata_path,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (writer->metadata_fd < 0) {
+ perror("open");
+ goto error_destroy;
+ }
+
+ g_free(metadata_path);
+ return writer;
+
+error_destroy:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(writer);
+error:
+ g_free(metadata_path);
+ return writer;
+}
+
+void bt_ctf_writer_destroy(struct bt_ctf_object *obj)
+{
+ struct bt_ctf_writer *writer;
+
+ writer = container_of(obj, struct bt_ctf_writer, base);
+ bt_ctf_writer_flush_metadata(writer);
+ if (writer->path) {
+ g_string_free(writer->path, TRUE);
+ }
+
+ if (writer->metadata_fd > 0) {
+ if (close(writer->metadata_fd)) {
+ perror("close");
+ }
+ }
+
+ bt_ctf_object_try_spec_release(&writer->trace->common.base);
+ g_free(writer);
+}
+
+struct bt_ctf_trace *bt_ctf_writer_get_trace(struct bt_ctf_writer *writer)
+{
+ struct bt_ctf_trace *trace = NULL;
+
+ if (!writer) {
+ goto end;
+ }
+
+ trace = writer->trace;
+ bt_ctf_object_get_ref(trace);
+end:
+ return trace;
+}
+
+struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
+ struct bt_ctf_stream_class *stream_class)
+{
+ struct bt_ctf_stream *stream = NULL;
+ int stream_class_count;
+ bt_bool stream_class_found = BT_FALSE;
+ int i;
+
+ if (!writer || !stream_class) {
+ goto error;
+ }
+
+ /* Make sure the stream class is part of the writer's trace */
+ stream_class_count = bt_ctf_trace_get_stream_class_count(writer->trace);
+ if (stream_class_count < 0) {
+ goto error;
+ }
+
+ for (i = 0; i < stream_class_count; i++) {
+ struct bt_ctf_stream_class *existing_stream_class =
+ bt_ctf_trace_get_stream_class_by_index(
+ writer->trace, i);
+
+ if (existing_stream_class == stream_class) {
+ stream_class_found = BT_TRUE;
+ }
+
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(existing_stream_class);
+
+ if (stream_class_found) {
+ break;
+ }
+ }
+
+ if (!stream_class_found) {
+ int ret = bt_ctf_trace_add_stream_class(writer->trace,
+ stream_class);
+
+ if (ret) {
+ goto error;
+ }
+ }
+
+ stream = bt_ctf_stream_create_with_id(stream_class, NULL, -1ULL);
+ if (!stream) {
+ goto error;
+ }
+
+ return stream;
+
+error:
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(stream);
+ return stream;
+}
+
+int bt_ctf_writer_add_environment_field(struct bt_ctf_writer *writer,
+ const char *name,
+ const char *value)
+{
+ int ret = -1;
+
+ if (!writer || !name || !value) {
+ goto end;
+ }
+
+ ret = bt_ctf_trace_set_environment_field_string(writer->trace,
+ name, value);
+end:
+ return ret;
+}
+
+int bt_ctf_writer_add_environment_field_int64(struct bt_ctf_writer *writer,
+ const char *name, int64_t value)
+{
+ int ret = -1;
+
+ if (!writer || !name) {
+ goto end;
+ }
+
+ ret = bt_ctf_trace_set_environment_field_integer(writer->trace, name,
+ value);
+end:
+ return ret;
+}
+
+int bt_ctf_writer_add_clock(struct bt_ctf_writer *writer,
+ struct bt_ctf_clock *clock)
+{
+ int ret = -1;
+
+ if (!writer || !clock) {
+ goto end;
+ }
+
+ ret = bt_ctf_trace_add_clock_class(writer->trace, clock->clock_class);
+end:
+ return ret;
+}
+
+char *bt_ctf_writer_get_metadata_string(struct bt_ctf_writer *writer)
+{
+ char *metadata_string = NULL;
+
+ if (!writer) {
+ goto end;
+ }
+
+ metadata_string = bt_ctf_trace_get_metadata_string(
+ writer->trace);
+end:
+ return metadata_string;
+}
+
+void bt_ctf_writer_flush_metadata(struct bt_ctf_writer *writer)
+{
+ int ret;
+ char *metadata_string = NULL;
+
+ if (!writer) {
+ goto end;
+ }
+
+ metadata_string = bt_ctf_trace_get_metadata_string(
+ writer->trace);
+ if (!metadata_string) {
+ goto end;
+ }
+
+ if (lseek(writer->metadata_fd, 0, SEEK_SET) == (off_t)-1) {
+ perror("lseek");
+ goto end;
+ }
+
+ if (ftruncate(writer->metadata_fd, 0)) {
+ perror("ftruncate");
+ goto end;
+ }
+
+ ret = write(writer->metadata_fd, metadata_string,
+ strlen(metadata_string));
+ if (ret < 0) {
+ perror("write");
+ goto end;
+ }
+end:
+ g_free(metadata_string);
+}
+
+int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
+ enum bt_ctf_byte_order byte_order)
+{
+ int ret = 0;
+
+ if (!writer || writer->frozen) {
+ ret = -1;
+ goto end;
+ }
+
+ if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+ if (BYTE_ORDER == LITTLE_ENDIAN) {
+ byte_order = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
+ } else {
+ byte_order = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
+ }
+ }
+
+ ret = bt_ctf_trace_set_native_byte_order(writer->trace,
+ byte_order);
+end:
+ return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_writer_freeze(struct bt_ctf_writer *writer)
+{
+ writer->frozen = 1;
+}
+
+static
+const unsigned int field_type_aliases_alignments[] = {
+ [FIELD_TYPE_ALIAS_UINT5_T] = 1,
+ [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
+ [FIELD_TYPE_ALIAS_UINT27_T] = 1,
+ [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
+};
+
+static
+const unsigned int field_type_aliases_sizes[] = {
+ [FIELD_TYPE_ALIAS_UINT5_T] = 5,
+ [FIELD_TYPE_ALIAS_UINT8_T] = 8,
+ [FIELD_TYPE_ALIAS_UINT16_T] = 16,
+ [FIELD_TYPE_ALIAS_UINT27_T] = 27,
+ [FIELD_TYPE_ALIAS_UINT32_T] = 32,
+ [FIELD_TYPE_ALIAS_UINT64_T] = 64,
+};
+
+BT_HIDDEN
+struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
+{
+ int ret;
+ unsigned int alignment, size;
+ struct bt_ctf_field_type *field_type = NULL;
+
+ if (alias >= NR_FIELD_TYPE_ALIAS) {
+ goto end;
+ }
+
+ alignment = field_type_aliases_alignments[alias];
+ size = field_type_aliases_sizes[alias];
+ field_type = bt_ctf_field_type_integer_create(size);
+ ret = bt_ctf_field_type_set_alignment(field_type, alignment);
+ if (ret) {
+ BT_CTF_OBJECT_PUT_REF_AND_RESET(field_type);
+ }
+end:
+ return field_type;
+}
+
+BT_HIDDEN
+const char *bt_ctf_get_byte_order_string(enum bt_ctf_byte_order byte_order)
+{
+ const char *string;
+
+ switch (byte_order) {
+ case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
+ string = "le";
+ break;
+ case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
+ string = "be";
+ break;
+ case BT_CTF_BYTE_ORDER_NATIVE:
+ string = "native";
+ break;
+ default:
+ abort();
+ }
+
+ return string;
+}
src = ''
for section in sections:
+ if 'ctf' in section.title.lower():
+ continue
+
src += '/* {} */\n'.format(section.title)
for filename in sorted(section.filenames):
babeltrace2/plugin/python-plugin-provider-internal.h \
babeltrace2/assert-internal.h \
babeltrace2/value-internal.h \
+ babeltrace2/ctf-writer/assert-pre-internal.h \
babeltrace2/ctf-writer/attributes-internal.h \
babeltrace2/ctf-writer/clock-class-internal.h \
babeltrace2/ctf-writer/clock-internal.h \
#include <babeltrace2/value.h>
#include <babeltrace2/version.h>
-/* Legacy API (for CTF writer) */
-#include <babeltrace2/ctf/events.h>
-
-/* CTF writer API */
-#include <babeltrace2/ctf-writer/clock-class.h>
-#include <babeltrace2/ctf-writer/clock.h>
-#include <babeltrace2/ctf-writer/event-fields.h>
-#include <babeltrace2/ctf-writer/event-types.h>
-#include <babeltrace2/ctf-writer/event.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/fields.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctf-writer/stream-class.h>
-#include <babeltrace2/ctf-writer/stream.h>
-#include <babeltrace2/ctf-writer/trace.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/visitor.h>
-#include <babeltrace2/ctf-writer/writer.h>
-
-/* Legacy API (for CTF writer) */
-#include <babeltrace2/ctf-ir/clock.h>
-#include <babeltrace2/ctf-ir/event-fields.h>
-#include <babeltrace2/ctf-ir/event-types.h>
-#include <babeltrace2/ctf-ir/event.h>
-#include <babeltrace2/ctf-ir/field-types.h>
-#include <babeltrace2/ctf-ir/fields.h>
-#include <babeltrace2/ctf-ir/stream-class.h>
-#include <babeltrace2/ctf-ir/stream.h>
-#include <babeltrace2/ctf-ir/trace.h>
-#include <babeltrace2/ctf-ir/utils.h>
-
/* Trace IR API */
#include <babeltrace2/trace-ir/clock-class-const.h>
#include <babeltrace2/trace-ir/clock-class.h>
--- /dev/null
+#ifndef BABELTRACE_CTF_WRITER_ASSERT_PRE_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_ASSERT_PRE_INTERNAL_H
+
+/*
+ * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 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.
+ */
+
+/*
+ * The macros in this header use macros defined in
+ * <babeltrace2/lib-logging-internal.h>. We don't want this header to
+ * automatically include <babeltrace2/lib-logging-internal.h> because you
+ * need to manually define BT_LOG_TAG before including
+ * <babeltrace2/lib-logging-internal.h> and it is unexpected that you
+ * also need to define it before including this header.
+ *
+ * This is a reminder that in order to use
+ * <babeltrace2/assert-pre-internal.h>, you also need to use logging
+ * explicitly.
+ */
+
+#ifndef BABELTRACE_LOGGING_INTERNAL_H
+# error Include <babeltrace2/logging-internal.h> before this header.
+#endif
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <babeltrace2/babeltrace-internal.h>
+
+#ifdef BT_DEV_MODE
+/*
+ * Asserts that the library precondition _cond is satisfied.
+ *
+ * If _cond is false, log a fatal statement using _fmt and the optional
+ * arguments using BT_LOGF(), and abort.
+ *
+ * To assert that a postcondition is satisfied or that some internal
+ * object/context/value is in the expected state, use BT_ASSERT().
+ */
+# define BT_CTF_ASSERT_PRE(_cond, _fmt, ...) \
+ do { \
+ if (!(_cond)) { \
+ BT_LOGF_STR("Library precondition not satisfied; error is:"); \
+ BT_LOGF((_fmt), ##__VA_ARGS__); \
+ BT_LOGF_STR("Aborting..."); \
+ abort(); \
+ } \
+ } while (0)
+
+/*
+ * Marks a function as being only used within a BT_CTF_ASSERT_PRE() context.
+ */
+# define BT_CTF_ASSERT_PRE_FUNC
+
+/*
+ * Prints the details of an unsatisfied precondition without immediately
+ * aborting. You should use this within a function which checks
+ * preconditions, but which is called from a BT_CTF_ASSERT_PRE() context, so
+ * that the function can still return its result for BT_CTF_ASSERT_PRE() to
+ * evaluate it.
+ *
+ * Example:
+ *
+ * BT_CTF_ASSERT_PRE_FUNC
+ * static inline bool check_complex_precond(...)
+ * {
+ * ...
+ *
+ * if (...) {
+ * BT_CTF_ASSERT_PRE_MSG("Invalid object: ...", ...);
+ * return false;
+ * }
+ *
+ * ...
+ * }
+ *
+ * ...
+ *
+ * BT_CTF_ASSERT_PRE(check_complex_precond(...),
+ * "Precondition is not satisfied: ...", ...);
+ */
+# define BT_CTF_ASSERT_PRE_MSG BT_LOGF
+#else
+# define BT_CTF_ASSERT_PRE(_cond, _fmt, ...) ((void) sizeof((void) (_cond), 0))
+# define BT_CTF_ASSERT_PRE_FUNC BT_UNUSED
+# define BT_CTF_ASSERT_PRE_MSG(_fmt, ...)
+#endif /* BT_DEV_MODE */
+
+/*
+ * Developer mode: asserts that a given variable is not NULL.
+ */
+#define BT_CTF_ASSERT_PRE_NON_NULL(_obj, _obj_name) \
+ BT_CTF_ASSERT_PRE((_obj) != NULL, "%s is NULL: ", _obj_name)
+
+/*
+ * Developer mode: asserts that a given object is NOT frozen. This macro
+ * checks the `frozen` field of _obj.
+ */
+#define BT_CTF_ASSERT_PRE_HOT(_obj, _obj_name, _fmt, ...) \
+ BT_CTF_ASSERT_PRE(!(_obj)->frozen, "%s is frozen" _fmt, _obj_name, \
+ ##__VA_ARGS__)
+
+/*
+ * Developer mode: asserts that a given index is less than a given size.
+ */
+#define BT_CTF_ASSERT_PRE_VALID_INDEX(_index, _length) \
+ BT_CTF_ASSERT_PRE((_index) < (_length), \
+ "Index is out of bounds: index=%" PRIu64 ", " \
+ "count=%" PRIu64, (uint64_t) (_index), (uint64_t) (_length))
+
+#endif /* BABELTRACE_CTF_WRITER_ASSERT_PRE_INTERNAL_H */
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_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
BT_ASSERT(event_class->name);
return event_class->name->str;
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
return event_class->id;
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
return event_class->log_level;
}
{
const char *emf_uri = NULL;
- BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
if (event_class->emf_uri->len > 0) {
emf_uri = event_class->emf_uri->str;
{
struct bt_ctf_field_type_common *context_ft = NULL;
- BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
if (!event_class->context_field_type) {
BT_LOGV("Event class has no context field type: "
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(event_class, "Event class");
return event_class->payload_field_type;
}
*/
#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
#include <babeltrace2/babeltrace-internal.h>
#include <babeltrace2/ctf-writer/event-class-internal.h>
#include <babeltrace2/ctf-writer/event-internal.h>
# 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))
+#define BT_CTF_ASSERT_PRE_EVENT_COMMON_HOT(_event, _name) \
+ BT_CTF_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_field_common *payload = NULL;
- BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
if (!event->payload_field) {
BT_LOGV("Event has no current payload field: addr=%p, "
{
struct bt_ctf_field_common *header = NULL;
- BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
if (!event->header_field) {
BT_LOGV("Event has no current header field: addr=%p, "
{
struct bt_ctf_field_common *context = NULL;
- BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
if (!event->context_field) {
BT_LOGV("Event has no current context field: addr=%p, "
{
struct bt_ctf_field_common *stream_event_context = NULL;
- BT_ASSERT_PRE_NON_NULL(event, "Event");
+ BT_CTF_ASSERT_PRE_NON_NULL(event, "Event");
if (!event->stream_event_context_field) {
BT_LOGV("Event has no current stream event context field: addr=%p, "
#include <stdint.h>
#include <stddef.h>
-#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
#include <babeltrace2/babeltrace-internal.h>
#include <babeltrace2/ctf-writer/clock-class-internal.h>
#include <babeltrace2/ctf-writer/field-types.h>
#include <babeltrace2/ctf-writer/object-internal.h>
#include <babeltrace2/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), \
+#define BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(_ft, _type_id, _name) \
+ BT_CTF_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_ASSERT_PRE_CTF_FT_HOT(_ft, _name) \
+ BT_CTF_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, \
#include <stdint.h>
#include <stddef.h>
-#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
#include <babeltrace2/babeltrace-internal.h>
#include <babeltrace2/common-internal.h>
#include <babeltrace2/ctf-writer/field-types-internal.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)), \
+#define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \
+ BT_CTF_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), \
+#define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(_field, _name) \
+ BT_CTF_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))
+#define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(_field, _name) \
+ BT_CTF_ASSERT_PRE_HOT((_field), (_name), ": field-addr=%p", (_field))
struct bt_ctf_field_common;
int ret = 0;
if (!field) {
- BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
+ BT_CTF_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
ret = -1;
goto end;
}
{
struct bt_ctf_field_type_common *ret = NULL;
- BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Field");
ret = field->type;
return ret;
}
{
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
"Field");
return (int64_t) sequence->length;
}
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field");
+ BT_CTF_ASSERT_PRE(((int64_t) length) >= 0,
"Invalid sequence length (too large): length=%" PRId64,
length);
- BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Sequence field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Sequence field");
if (unlikely(length > sequence->elements->len)) {
/* Make more room */
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_ASSERT_PRE_NON_NULL(field, "Structure field");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Field name");
+ BT_CTF_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;
{
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_ASSERT_PRE_NON_NULL(field, "Structure field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
BT_CTF_FIELD_TYPE_ID_STRUCT, "Field");
- BT_ASSERT_PRE(index < structure->fields->len,
+ BT_CTF_ASSERT_PRE(index < structure->fields->len,
"Index is out of bound: struct-field-addr=%p, "
"index=%" PRIu64 ", count=%u", field, index,
structure->fields->len);
{
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Array field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_ARRAY,
"Field");
- BT_ASSERT_PRE(index < array->elements->len,
+ BT_CTF_ASSERT_PRE(index < array->elements->len,
"Index is out of bound: array-field-addr=%p, "
"index=%" PRIu64 ", count=%u", field,
index, array->elements->len);
{
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
"Field");
- BT_ASSERT_PRE(index < sequence->length,
+ BT_CTF_ASSERT_PRE(index < sequence->length,
"Index is out of bound: seq-field-addr=%p, "
"index=%" PRIu64 ", count=%u", field, index,
sequence->elements->len);
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_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_CTF_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 */
{
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_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
+ BT_CTF_ASSERT_PRE(variant->current_field,
"Variant field has no current field: field-addr=%p", variant_field);
return variant->current_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_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
+ BT_CTF_ASSERT_PRE(variant->current_field,
"Variant field has no current field: field-addr=%p", variant_field);
*tag = variant->tag_value.i;
return 0;
{
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_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
+ BT_CTF_ASSERT_PRE(variant->current_field,
"Variant field has no current field: field-addr=%p", variant_field);
*tag = variant->tag_value.u;
return 0;
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_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
BT_CTF_FIELD_TYPE_ID_FLOAT, "Field");
*value = floating_point->payload;
return 0;
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_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Floating point number field");
+ BT_CTF_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);
{
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_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
BT_CTF_FIELD_TYPE_ID_STRING, "Field");
return (const char *) string->buf->data;
}
{
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_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+ BT_CTF_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);
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_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+ BT_CTF_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,
+ BT_CTF_ASSERT_PRE(memchr(value, '\0', length) == NULL,
"String value to append contains a null character: "
"partial-value=\"%.32s\", length=%u", value, length);
int bt_ctf_field_common_string_append(struct bt_ctf_field_common *field,
const char *value)
{
- BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
return bt_ctf_field_common_string_append_len(field, value,
strlen(value));
}
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_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_CTF_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+ BT_CTF_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,
}
}
-BT_ASSERT_PRE_FUNC
+BT_CTF_ASSERT_PRE_FUNC
static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
{
bool ret = true;
return ret;
}
-BT_ASSERT_PRE_FUNC
+BT_CTF_ASSERT_PRE_FUNC
static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
{
bool ret = true;
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
return stream_class->name->len > 0 ? stream_class->name->str : NULL;
}
{
int64_t ret;
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_CTF_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\"",
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_CTF_ASSERT_PRE(index < stream_class->event_classes->len,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u",
index, stream_class->event_classes->len);
{
int64_t id_key = (int64_t) id;
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- BT_ASSERT_PRE(id_key >= 0,
+ BT_CTF_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_CTF_ASSERT_PRE(id_key >= 0,
"Invalid event class ID: %" PRIu64, id);
return g_hash_table_lookup(stream_class->event_classes_ht,
&id_key);
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
return stream_class->packet_context_field_type;
}
{
struct bt_ctf_field_type_common *ret = NULL;
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_CTF_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: "
{
struct bt_ctf_field_type_common *ret = NULL;
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_CTF_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
if (!stream_class->event_context_field_type) {
goto end;
*/
#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
#include <babeltrace2/babeltrace-internal.h>
#include <babeltrace2/ctf-writer/stream-internal.h>
#include <babeltrace2/ctf-writer/stream.h>
static inline
const char *bt_ctf_stream_common_get_name(struct bt_ctf_stream_common *stream)
{
- BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ BT_CTF_ASSERT_PRE_NON_NULL(stream, "Stream");
return stream->name ? stream->name->str : NULL;
}
{
int64_t ret;
- BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ BT_CTF_ASSERT_PRE_NON_NULL(stream, "Stream");
ret = stream->id;
if (ret < 0) {
BT_LOGV("Stream's ID is not set: addr=%p, name=\"%s\"",
* http://www.efficios.com/ctf
*/
-#include <babeltrace2/assert-pre-internal.h>
+#include <babeltrace2/ctf-writer/assert-pre-internal.h>
#include <babeltrace2/babeltrace-internal.h>
#include <babeltrace2/compat/uuid-internal.h>
#include <babeltrace2/ctf-writer/attributes-internal.h>
static inline
const char *bt_ctf_trace_common_get_name(struct bt_ctf_trace_common *trace)
{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return trace->name ? trace->name->str : NULL;
}
static inline
const unsigned char *bt_ctf_trace_common_get_uuid(struct bt_ctf_trace_common *trace)
{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return trace->uuid_set ? trace->uuid : NULL;
}
{
int64_t ret;
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
ret = bt_ctf_attributes_get_count(trace->environment);
BT_ASSERT(ret >= 0);
return ret;
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return bt_ctf_attributes_get_field_name(trace->environment, index);
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return bt_ctf_attributes_borrow_field_value(trace->environment, index);
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
return bt_ctf_attributes_borrow_field_value_by_name(trace->environment,
name);
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return trace->clock_classes->len;
}
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE(index < trace->clock_classes->len,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u",
index, trace->clock_classes->len);
static inline
int64_t bt_ctf_trace_common_get_stream_count(struct bt_ctf_trace_common *trace)
{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return (int64_t) trace->streams->len;
}
struct bt_ctf_trace_common *trace,
uint64_t index)
{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(index < trace->streams->len,
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE(index < trace->streams->len,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u",
index, trace->streams->len);
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return (int64_t) trace->stream_classes->len;
}
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE(index < trace->stream_classes->len,
"Index is out of bounds: index=%" PRIu64 ", "
"count=%u",
index, trace->stream_classes->len);
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,
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE(id >= 0,
"Invalid stream class ID: %" PRIu64, id_param);
for (i = 0; i < trace->stream_classes->len; i++) {
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
for (i = 0; i < trace->clock_classes->len; i++) {
struct bt_ctf_clock_class *cur_clk =
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return trace->native_byte_order;
}
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");
+ BT_CTF_ASSERT_PRE_NON_NULL(trace, "Trace");
return trace->packet_header_field_type;
}
-SUBDIRS = trace-ir ctf-writer prio_heap plugin graph .
+SUBDIRS = trace-ir prio_heap plugin graph
-lib_LTLIBRARIES = libbabeltrace2.la libbabeltrace2-ctf.la
+lib_LTLIBRARIES = libbabeltrace2.la
libbabeltrace2_la_SOURCES = \
babeltrace2.c \
graph/libgraph.la \
plugin/libplugin.la \
trace-ir/libtrace-ir.la \
- ctf-writer/libctf-writer.la \
$(top_builddir)/logging/libbabeltrace2-logging.la \
$(top_builddir)/common/libbabeltrace2-common.la \
- $(top_builddir)/ctfser/libbabeltrace2-ctfser.la \
$(top_builddir)/compat/libcompat.la
if ENABLE_BUILT_IN_PYTHON_PLUGIN_SUPPORT
libbabeltrace2_la_LIBADD += $(top_builddir)/python-plugin-provider/libbabeltrace2-python-plugin-provider.la
endif
-
-# FIXME: Should we drop this? We changed the basename of the library,
-# libbabeltrace2 is not a drop-in replacement for libbabeltrace anymore.
-#
-# Build a libbabeltrace2-ctf library for backwards compatibility.
-# CTF writer used to be in libbabeltrace2-ctf in Babeltrace 1, so this
-# file must still exist. As of Babeltrace 2, CTF writer is implemented
-# in libbabeltrace2.
-libbabeltrace2_ctf_la_SOURCES = $(libbabeltrace2_la_SOURCES)
-libbabeltrace2_ctf_la_LDFLAGS = $(LT_NO_UNDEFINED) \
- -version-info $(BABELTRACE_LIBRARY_VERSION)
-
-libbabeltrace2_ctf_la_LIBADD = \
- graph/libgraph.la \
- trace-ir/libtrace-ir.la \
- ctf-writer/libctf-writer.la \
- $(top_builddir)/logging/libbabeltrace2-logging.la \
- $(top_builddir)/common/libbabeltrace2-common.la \
- $(top_builddir)/ctfser/libbabeltrace2-ctfser.la \
- $(top_builddir)/compat/libcompat.la
+++ /dev/null
-noinst_LTLIBRARIES = libctf-writer.la
-
-libctf_writer_la_SOURCES = \
- attributes.c \
- clock.c \
- clock-class.c \
- event.c \
- event-class.c \
- field-path.c \
- fields.c \
- field-types.c \
- field-wrapper.c \
- functor.c \
- object.c \
- object-pool.c \
- resolve.c \
- stream.c \
- stream-class.c \
- trace.c \
- utils.c \
- validation.c \
- values.c \
- visitor.c \
- writer.c
-
-libctf_writer_la_LIBADD = $(UUID_LIBS)
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/babeltrace-internal.h>
-#include <babeltrace2/compat/string-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctf-writer/values-internal.h>
-#include <babeltrace2/ctf-writer/values-internal.h>
-#include <babeltrace2/ctf-writer/values-internal.h>
-#include <inttypes.h>
-
-#define BT_CTF_ATTR_NAME_INDEX 0
-#define BT_CTF_ATTR_VALUE_INDEX 1
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_attributes_create(void)
-{
- struct bt_ctf_private_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_ctf_private_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_ctf_private_value *attr_obj)
-{
- BT_LOGD("Destroying attributes object: addr=%p", attr_obj);
- bt_ctf_object_put_ref(attr_obj);
-}
-
-BT_HIDDEN
-int64_t bt_ctf_attributes_get_count(struct bt_ctf_private_value *attr_obj)
-{
- return bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj));
-}
-
-BT_HIDDEN
-const char *bt_ctf_attributes_get_field_name(struct bt_ctf_private_value *attr_obj,
- uint64_t index)
-{
- const char *ret = NULL;
- struct bt_ctf_private_value *attr_field_obj = NULL;
- struct bt_ctf_private_value *attr_field_name_obj = NULL;
-
- if (!attr_obj) {
- BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
- goto end;
- }
-
- if (index >= bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj))) {
- BT_LOGW("Invalid parameter: index is out of bounds: "
- "index=%" PRIu64 ", count=%" PRId64,
- index, bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj)));
- goto end;
- }
-
- attr_field_obj = bt_ctf_private_value_array_borrow_element_by_index(
- 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_ctf_private_value_array_borrow_element_by_index(
- 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;
- }
-
- ret = bt_ctf_value_string_get(
- bt_ctf_private_value_as_value(attr_field_name_obj));
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_attributes_borrow_field_value(struct bt_ctf_private_value *attr_obj,
- uint64_t index)
-{
- struct bt_ctf_private_value *value_obj = NULL;
- struct bt_ctf_private_value *attr_field_obj = NULL;
-
- if (!attr_obj) {
- BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
- goto end;
- }
-
- if (index >= bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj))) {
- BT_LOGW("Invalid parameter: index is out of bounds: "
- "index=%" PRIu64 ", count=%" PRId64,
- index, bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(attr_obj)));
- goto end;
- }
-
- attr_field_obj = bt_ctf_private_value_array_borrow_element_by_index(
- 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_ctf_private_value_array_borrow_element_by_index(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_ctf_private_value *bt_ctf_attributes_borrow_field_by_name(
- struct bt_ctf_private_value *attr_obj, const char *name)
-{
- uint64_t i;
- int64_t attr_size;
- struct bt_ctf_private_value *value_obj = NULL;
- struct bt_ctf_private_value *attr_field_name_obj = NULL;
-
- attr_size = bt_ctf_value_array_get_size(bt_ctf_private_value_as_value(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) {
- const char *field_name;
-
- value_obj = bt_ctf_private_value_array_borrow_element_by_index(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_ctf_private_value_array_borrow_element_by_index(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;
- }
-
- field_name = bt_ctf_value_string_get(
- bt_ctf_private_value_as_value(attr_field_name_obj));
-
- 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_ctf_private_value *attr_obj,
- const char *name, struct bt_ctf_private_value *value_obj)
-{
- int ret = 0;
- struct bt_ctf_private_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_ctf_private_value_array_set_element_by_index(
- attr_field_obj, BT_CTF_ATTR_VALUE_INDEX,
- bt_ctf_private_value_as_value(value_obj));
- attr_field_obj = NULL;
- goto end;
- }
-
- attr_field_obj = bt_ctf_private_value_array_create();
- if (!attr_field_obj) {
- BT_LOGE_STR("Failed to create empty array value.");
- ret = -1;
- goto end;
- }
-
- ret = bt_ctf_private_value_array_append_string_element(attr_field_obj, name);
- ret |= bt_ctf_private_value_array_append_element(attr_field_obj,
- bt_ctf_private_value_as_value(value_obj));
- if (ret) {
- BT_LOGE("Cannot append elements to array value: addr=%p",
- attr_field_obj);
- goto end;
- }
-
- ret = bt_ctf_private_value_array_append_element(attr_obj,
- bt_ctf_private_value_as_value(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_ctf_object_put_ref(attr_field_obj);
- return ret;
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_attributes_borrow_field_value_by_name(
- struct bt_ctf_private_value *attr_obj, const char *name)
-{
- struct bt_ctf_private_value *value_obj = NULL;
- struct bt_ctf_private_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_ctf_private_value_array_borrow_element_by_index(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_ctf_private_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_ctf_value_array_get_size(bt_ctf_private_value_as_value(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_ctf_private_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_ctf_value_freeze(bt_ctf_private_value_as_value(obj));
- }
-
-end:
- return ret;
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/compat/uuid-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/types.h>
-#include <babeltrace2/compat/string-internal.h>
-#include <inttypes.h>
-#include <babeltrace2/ctf-writer/object-internal.h>
-#include <babeltrace2/assert-internal.h>
-
-static
-void bt_ctf_clock_class_destroy(struct bt_ctf_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_ctf_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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_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;
-}
+++ /dev/null
-/*
- * clock.c
- *
- * Babeltrace CTF writer - Clock
- *
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017 Philippe Proulx <pproulx@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"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compat/uuid-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/clock-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/ctf-writer/object-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <inttypes.h>
-
-static
-void bt_ctf_clock_destroy(struct bt_ctf_object *obj);
-
-struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
-{
- int ret;
- struct bt_ctf_clock *clock = NULL;
- unsigned char cc_uuid[BABELTRACE_UUID_LEN];
-
- BT_ASSERT_PRE_NON_NULL(name, "Name");
- clock = g_new0(struct bt_ctf_clock, 1);
- if (!clock) {
- goto error;
- }
-
- bt_ctf_object_init_shared(&clock->base, bt_ctf_clock_destroy);
- clock->value = 0;
-
- /* Pre-2.0.0 backward compatibility: default frequency is 1 GHz */
- clock->clock_class = (void *) bt_ctf_clock_class_create(name, 1000000000);
- if (!clock->clock_class) {
- goto error;
- }
-
- /* Automatically set clock class's UUID. */
- ret = bt_uuid_generate(cc_uuid);
- if (ret) {
- goto error;
- }
-
- ret = bt_ctf_clock_class_set_uuid(clock->clock_class, cc_uuid);
- BT_ASSERT(ret == 0);
- return clock;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(clock);
- return clock;
-}
-
-const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock)
-{
- BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
- 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_ctf_clock_class *cc;
-
- BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
- cc = clock->clock_class;
-
- /* Common case where cycles are actually nanoseconds */
- if (cc->frequency == 1000000000) {
- value = time;
- } else {
- value = (uint64_t) (((double) time *
- (double) cc->frequency) / 1e9);
- }
-
- BT_ASSERT_PRE(clock->value <= value,
- "CTF writer clock value must be updated monotonically: "
- "prev-value=%" PRId64 ", new-value=%" PRId64,
- clock->value, value);
- clock->value = value;
- return 0;
-}
-
-BT_HIDDEN
-int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value)
-{
- BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- *value = clock->value;
- return 0;
-}
-
-static
-void bt_ctf_clock_destroy(struct bt_ctf_object *obj)
-{
- struct bt_ctf_clock *clock;
-
- clock = container_of(obj, struct bt_ctf_clock, base);
- bt_ctf_object_put_ref(clock->clock_class);
- g_free(clock);
-}
-
-BT_HIDDEN
-void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
- struct metadata_context *context)
-{
- unsigned char *uuid;
-
- BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
- "name=\"%s\", metadata-context-addr=%p", clock_class,
- bt_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_ctf_clock_class_get_name(clock_class),
- context);
- return;
- }
-
- uuid = clock_class->uuid;
- g_string_append(context->string, "clock {\n");
- g_string_append_printf(context->string, "\tname = %s;\n",
- clock_class->name->str);
-
- if (clock_class->uuid_set) {
- g_string_append_printf(context->string,
- "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]);
- }
-
- if (clock_class->description) {
- g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
- clock_class->description->str);
- }
-
- g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
- clock_class->frequency);
- g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
- clock_class->precision);
- g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
- clock_class->offset_s);
- g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
- clock_class->offset);
- g_string_append_printf(context->string, "\tabsolute = %s;\n",
- clock_class->absolute ? "true" : "false");
- g_string_append(context->string, "};\n\n");
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-EVENT-CLASS"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/attributes-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/event-internal.h>
-#include <babeltrace2/ctf-writer/event.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/stream-class.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/validation-internal.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/types.h>
-#include <babeltrace2/ctf-writer/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_ctf_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_ctf_object_put_ref(event_class->context_field_type);
- BT_LOGD_STR("Putting payload field type.");
- bt_ctf_object_put_ref(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_ctf_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_ctf_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_ctf_object *obj)
-{
- bt_ctf_event_class_common_finalize(obj);
- g_free(obj);
-}
-
-struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
-{
- struct bt_ctf_event_class *ctf_event_class = NULL;
- int ret;
-
- if (!name) {
- BT_LOGW_STR("Invalid parameter: name is NULL.");
- goto error;
- }
-
- BT_LOGD("Creating event class object: name=\"%s\"",
- name);
- ctf_event_class = g_new0(struct bt_ctf_event_class, 1);
- if (!ctf_event_class) {
- BT_LOGE_STR("Failed to allocate one event class.");
- goto error;
- }
-
- ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class),
- name, bt_ctf_event_class_destroy,
- (bt_ctf_field_type_structure_create_func)
- bt_ctf_field_type_structure_create);
- if (ret) {
- goto error;
- }
-
- goto end;
-
-error:
- bt_ctf_object_put_ref(ctf_event_class);
-
-end:
- return ctf_event_class;
-}
-
-const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
-{
- return bt_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_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_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_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_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_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_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
- emf_uri);
-}
-
-struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
- struct bt_ctf_event_class *event_class)
-{
- BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- return bt_ctf_object_get_ref(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_ctf_object_get_ref(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_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_ctf_object_get_ref(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_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,
- struct bt_ctf_field_type *type,
- const char *name)
-{
- int ret = 0;
-
- if (!event_class || !type) {
- BT_LOGW("Invalid parameter: event class or field type is NULL: "
- "event-class-addr=%p, field-type-addr=%p",
- event_class, type);
- ret = -1;
- goto end;
- }
-
- if (!bt_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),
- bt_ctf_event_class_get_id(event_class),
- name);
- ret = -1;
- goto end;
- }
-
- if (event_class->common.frozen) {
- BT_LOGW("Invalid parameter: event class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
-
- if (!event_class->common.payload_field_type) {
- BT_LOGW("Event class has no payload field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
-
- BT_ASSERT(bt_ctf_field_type_common_get_type_id(
- event_class->common.payload_field_type) ==
- BT_CTF_FIELD_TYPE_ID_STRUCT);
- ret = bt_ctf_field_type_structure_add_field(
- (void *) event_class->common.payload_field_type,
- (void *) type, name);
- BT_LOGV("Added field to event class's payload field type: "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p",
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class), name, type);
-end:
- return ret;
-}
-
-int64_t bt_ctf_event_class_get_payload_type_field_count(
- struct bt_ctf_event_class *event_class)
-{
- int64_t ret;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = (int64_t) -1;
- goto end;
- }
-
- if (!event_class->common.payload_field_type) {
- BT_LOGV("Event class has no payload field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- ret = (int64_t) -1;
- goto end;
- }
-
- BT_ASSERT(bt_ctf_field_type_common_get_type_id(
- event_class->common.payload_field_type) ==
- 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;
-}
-
-int bt_ctf_event_class_get_payload_type_field_by_index(
- struct bt_ctf_event_class *event_class,
- const char **field_name, struct bt_ctf_field_type **field_type,
- uint64_t index)
-{
- int ret;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (!event_class->common.payload_field_type) {
- BT_LOGV("Event class has no payload field type: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64,
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class), index);
- ret = -1;
- goto end;
- }
-
- BT_ASSERT(bt_ctf_field_type_common_get_type_id(
- event_class->common.payload_field_type) ==
- 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);
-
-end:
- return ret;
-}
-
-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_ctf_field_type *field_type = NULL;
-
- if (!event_class || !name) {
- BT_LOGW("Invalid parameter: event class or name is NULL: "
- "event-class-addr=%p, name-addr=%p",
- event_class, name);
- goto end;
- }
-
- if (!event_class->common.payload_field_type) {
- BT_LOGV("Event class has no payload field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- goto end;
- }
-
- BT_ASSERT(bt_ctf_field_type_common_get_type_id(
- event_class->common.payload_field_type) ==
- BT_CTF_FIELD_TYPE_ID_STRUCT);
- name_quark = g_quark_try_string(name);
- if (!name_quark) {
- BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
- goto end;
- }
-
- /*
- * No need to increment field_type's reference count since getting it
- * from the structure already does.
- */
- field_type = (void *)
- bt_ctf_field_type_structure_get_field_type_by_name(
- (void *) event_class->common.payload_field_type, name);
-
-end:
- return field_type;
-}
-
-BT_HIDDEN
-int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
- struct metadata_context *context)
-{
- int ret = 0;
- struct bt_ctf_value *attr_value = NULL;
-
- BT_ASSERT(event_class);
- BT_ASSERT(context);
- BT_LOGD("Serializing event class's metadata: "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", metadata-context-addr=%p",
- event_class, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class), context);
- context->current_indentation_level = 1;
- g_string_assign(context->field_name, "");
- g_string_append(context->string, "event {\n");
-
- /* Serialize attributes */
- g_string_append_printf(context->string, "\tname = \"%s\";\n",
- event_class->common.name->str);
- BT_ASSERT(event_class->common.id >= 0);
- g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
- event_class->common.id);
- g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
- bt_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_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
- g_string_append_printf(context->string, "\tloglevel = %d;\n",
- (int) event_class->common.log_level);
- }
-
- if (event_class->common.emf_uri->len > 0) {
- g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
- event_class->common.emf_uri->str);
- }
-
- /* Serialize context field type */
- if (event_class->common.context_field_type) {
- g_string_append(context->string, "\tcontext := ");
- BT_LOGD_STR("Serializing event class's context field type metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) event_class->common.context_field_type,
- context);
- if (ret) {
- BT_LOGW("Cannot serialize event class's context field type's metadata: "
- "ret=%d", ret);
- goto end;
- }
- g_string_append(context->string, ";\n");
- }
-
- /* Serialize payload field type */
- if (event_class->common.payload_field_type) {
- g_string_append(context->string, "\tfields := ");
- BT_LOGD_STR("Serializing event class's payload field type metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) event_class->common.payload_field_type,
- context);
- if (ret) {
- BT_LOGW("Cannot serialize event class's payload field type's metadata: "
- "ret=%d", ret);
- goto end;
- }
- g_string_append(context->string, ";\n");
- }
-
- g_string_append(context->string, "};\n\n");
-
-end:
- context->current_indentation_level = 0;
- BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
- return ret;
-}
-
-struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
- struct bt_ctf_event_class *event_class, const char *name)
-{
- GQuark name_quark;
- struct bt_ctf_field_type *field_type = NULL;
-
- if (!event_class || !name) {
- BT_LOGW("Invalid parameter: event class or name is NULL: "
- "event-class-addr=%p, name-addr=%p",
- event_class, name);
- goto end;
- }
-
- if (!event_class->common.payload_field_type) {
- BT_LOGV("Event class has no payload field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class,
- bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- goto end;
- }
-
- BT_ASSERT(event_class->common.payload_field_type->id ==
- BT_CTF_FIELD_TYPE_ID_STRUCT);
- name_quark = g_quark_try_string(name);
- if (!name_quark) {
- BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
- goto end;
- }
-
- /*
- * No need to increment field_type's reference count since getting it
- * from the structure already does.
- */
- field_type = bt_ctf_object_get_ref(
- bt_ctf_field_type_common_structure_borrow_field_type_by_name(
- event_class->common.payload_field_type, name));
-
-end:
- return field_type;
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-EVENT"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/attributes-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/clock-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/event-internal.h>
-#include <babeltrace2/ctf-writer/event.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/fields.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/stream-class.h>
-#include <babeltrace2/ctf-writer/stream-internal.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/trace.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/validation-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <inttypes.h>
-
-static
-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_ctf_private_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 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_ctf_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_ctf_object_get_ref(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_ctf_object_init_shared_with_parent(&event->base, release_func);
- } else {
- bt_ctf_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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(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_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.");
- }
-
- return ret;
-}
-
-static
-void destroy_event_header_field(struct bt_ctf_field_wrapper *field_wrapper)
-{
- BT_ASSERT(field_wrapper);
- bt_ctf_object_put_ref(field_wrapper->field);
- bt_ctf_field_wrapper_destroy(field_wrapper);
-}
-
-static
-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_ctf_field_wrapper *field_wrapper = NULL;
- struct bt_ctf_field *field = bt_ctf_field_create((void *) ft);
-
- if (!field) {
- goto error;
- }
-
- field_wrapper = bt_ctf_field_wrapper_new(NULL);
- if (!field_wrapper) {
- goto error;
- }
-
- field_wrapper->field = (void *) field;
- field = NULL;
- goto end;
-
-error:
- bt_ctf_object_put_ref(field);
-
- if (field_wrapper) {
- destroy_event_header_field(field_wrapper);
- field_wrapper = NULL;
- }
-
-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_CTF_OBJECT_PUT_REF_AND_RESET(field_wrapper->field);
- bt_ctf_field_wrapper_destroy(field_wrapper);
-}
-
-static
-void bt_ctf_event_destroy(struct bt_ctf_object *obj)
-{
- bt_ctf_event_common_finalize(obj, (void *) bt_ctf_object_put_ref,
- (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_ctf_clock_class *expected_clock_class = NULL;
-
- event = g_new0(struct bt_ctf_event, 1);
- if (!event) {
- BT_LOGE_STR("Failed to allocate one CTF writer event.");
- goto error;
- }
-
- if (event_class) {
- struct bt_ctf_stream_class *stream_class =
- BT_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 = stream_class->clock->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_ctf_validation_flag_copy_field_type_func)
- bt_ctf_field_type_copy,
- false, map_clock_classes_func,
- (create_field_func) bt_ctf_field_create,
- (release_field_func) bt_ctf_object_put_ref,
- (create_header_field_func) create_event_header_field,
- (release_header_field_func) destroy_event_header_field);
- if (ret) {
- /* bt_ctf_event_common_initialize() logs errors */
- goto error;
- }
-
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(event);
-
-end:
- return event;
-}
-
-struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- return bt_ctf_object_get_ref(bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event)));
-}
-
-BT_HIDDEN
-struct bt_ctf_stream *bt_ctf_event_borrow_stream(struct bt_ctf_event *event)
-{
- BT_ASSERT(event);
- return (struct bt_ctf_stream *)
- bt_ctf_object_borrow_parent(&BT_CTF_TO_COMMON(event)->base);
-}
-
-struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- return bt_ctf_object_get_ref(bt_ctf_event_borrow_stream(event));
-}
-
-int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name,
- struct bt_ctf_field *field)
-{
- BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_NON_NULL(field, "Payload field");
- BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
- return bt_ctf_field_structure_set_field_by_name(
- (void *) event->common.payload_field, name, field);
-}
-
-struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
- const char *name)
-{
- struct bt_ctf_field *field = NULL;
-
- BT_ASSERT_PRE_NON_NULL(event, "Event");
-
- if (name) {
- field = bt_ctf_field_structure_get_field_by_name(
- BT_CTF_FROM_COMMON(event->common.payload_field), name);
- } else {
- field = BT_CTF_FROM_COMMON(event->common.payload_field);
- bt_ctf_object_get_ref(field);
- }
-
- return field;
-}
-
-struct bt_ctf_field *bt_ctf_event_get_payload_field(
- struct bt_ctf_event *event)
-{
- return bt_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(bt_ctf_event_common_borrow_stream_event_context(
- BT_CTF_TO_COMMON(event)));
-}
-
-BT_HIDDEN
-int bt_ctf_event_serialize(struct bt_ctf_event *event,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int ret = 0;
-
- BT_ASSERT(event);
- BT_ASSERT(ctfser);
-
- BT_LOGV_STR("Serializing event's context field.");
- if (event->common.context_field) {
- ret = bt_ctf_field_serialize_recursive(
- (void *) event->common.context_field, ctfser,
- native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize event's context field: "
- "event-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- event,
- bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class));
- goto end;
- }
- }
-
- BT_LOGV_STR("Serializing event's payload field.");
- if (event->common.payload_field) {
- ret = bt_ctf_field_serialize_recursive(
- (void *) event->common.payload_field, ctfser,
- native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize event's payload field: "
- "event-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- event,
- bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class));
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-void _bt_ctf_event_freeze(struct bt_ctf_event *event)
-{
- _bt_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_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_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-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_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-addr=%p, header-ft-addr=%p",
- event,
- bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
- }
-
- bt_ctf_object_put_ref(event->common.header_field->field);
- event->common.header_field->field = bt_ctf_object_get_ref(header);
- BT_LOGV("Set event's header field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "header-field-addr=%p",
- event, bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class), header);
- return 0;
-}
-
-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_CTF_TO_COMMON(event), "Event");
-
- if (payload) {
- 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-addr=%p, ft-addr=%p, "
- "expected-ft-addr=%p",
- event,
- ((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-addr=%p, payload-ft-addr=%p",
- event, event->common.class->payload_field_type);
- }
-
- bt_ctf_object_put_ref(event->common.payload_field);
- event->common.payload_field = bt_ctf_object_get_ref(payload);
- BT_LOGV("Set event's payload field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "payload-field-addr=%p",
- event, bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class), payload);
- return 0;
-}
-
-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_CTF_TO_COMMON(event), "Event");
-
- if (context) {
- 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-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-addr=%p, context-ft-addr=%p",
- event, event->common.class->context_field_type);
- }
-
- bt_ctf_object_put_ref(event->common.context_field);
- event->common.context_field = bt_ctf_object_get_ref(context);
- BT_LOGV("Set event's context field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "context-field-addr=%p",
- event, bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class), context);
- return 0;
-}
-
-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_CTF_TO_COMMON(event), "Event");
-
- if (stream_event_context) {
- 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-addr=%p, ft-addr=%p, "
- "expected-ft-addr=%p",
- event,
- ((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_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-addr=%p, context-ft-addr=%p",
- event,
- bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
- }
-
- bt_ctf_object_put_ref(event->common.stream_event_context_field);
- event->common.stream_event_context_field = bt_ctf_object_get_ref(stream_event_context);
- BT_LOGV("Set event's stream event context field: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "stream-event-context-field-addr=%p",
- event, bt_ctf_event_class_common_get_name(event->common.class),
- bt_ctf_event_class_common_get_id(event->common.class),
- stream_event_context);
- return 0;
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/ctf-writer/field-path-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <glib.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdint.h>
-
-static
-void field_path_destroy(struct bt_ctf_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_ctf_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_CTF_OBJECT_PUT_REF_AND_RESET(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;
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-FIELD-TYPES"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/clock-internal.h>
-#include <babeltrace2/ctf-writer/field-path-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/fields.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object-internal.h>
-#include <babeltrace2/ctf-writer/object.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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_get_ref(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_ctf_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_ctf_object_put_ref(ft->mapped_clock_class);
- g_free(ft);
-}
-
-BT_HIDDEN
-void bt_ctf_field_type_common_floating_point_destroy(struct bt_ctf_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_ctf_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_ctf_object_put_ref(ft->container_ft);
- g_free(ft);
-}
-
-BT_HIDDEN
-void bt_ctf_field_type_common_string_destroy(struct bt_ctf_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_ctf_object_put_ref(field->type);
-}
-
-BT_HIDDEN
-void bt_ctf_field_type_common_structure_destroy_recursive(struct bt_ctf_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_ctf_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_ctf_object_put_ref(ft->element_ft);
- g_free(ft);
-}
-
-BT_HIDDEN
-void bt_ctf_field_type_common_sequence_destroy_recursive(struct bt_ctf_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_ctf_object_put_ref(ft->element_ft);
- g_string_free(ft->length_field_name, TRUE);
- BT_LOGD_STR("Putting length field path.");
- bt_ctf_object_put_ref(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_ctf_object_put_ref(choice->type);
-
- if (choice->ranges) {
- g_array_free(choice->ranges, TRUE);
- }
-}
-
-BT_HIDDEN
-void bt_ctf_field_type_common_variant_destroy_recursive(struct bt_ctf_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_ctf_object_put_ref(ft->tag_ft);
- BT_LOGD_STR("Putting tag field path.");
- bt_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_ctf_object_put_ref(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_ctf_object_init_shared(&iter->base, bt_ctf_field_type_enum_iter_destroy);
- iter->enumeration_ft = bt_ctf_object_get_ref(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_ctf_object_put_ref(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_ctf_object_put_ref(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_ctf_object_put_ref(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_ctf_object_put_ref(int_ft->mapped_clock_class);
- int_ft->mapped_clock_class = bt_ctf_object_get_ref(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_ctf_object_put_ref(field->type);
- field->type = bt_ctf_object_get_ref(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_CTF_OBJECT_PUT_REF_AND_RESET(array_ft->element_ft);
- }
-
- array_ft->element_ft = bt_ctf_object_get_ref(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_CTF_OBJECT_PUT_REF_AND_RESET(seq_ft->element_ft);
- }
-
- seq_ft->element_ft = element_ft;
- bt_ctf_object_get_ref(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_ctf_object_get_ref(path);
- BT_CTF_OBJECT_MOVE_REF(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_ctf_object_get_ref(path);
- BT_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(var_ft->tag_ft);
- var_ft->tag_ft = bt_ctf_object_get_ref(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_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_object_put_ref(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);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
- struct bt_ctf_field_type *ft);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
- struct bt_ctf_field_type *ft);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
- struct bt_ctf_field_type *ft);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
- struct bt_ctf_field_type *ft);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
- struct bt_ctf_field_type *ft);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
- struct bt_ctf_field_type *type);
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_string_copy(
- struct bt_ctf_field_type *type);
-
-static struct bt_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_ctf_field_type_common_integer_compare,
-};
-
-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_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_ctf_field_type_common_floating_point_compare,
-};
-
-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_ctf_field_type_common_enumeration_compare_recursive,
-};
-
-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_ctf_field_type_common_method_copy)
- bt_ctf_field_type_string_copy,
- .compare = bt_ctf_field_type_common_string_compare,
-};
-
-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_ctf_field_type_common_array_compare_recursive,
-};
-
-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_ctf_field_type_common_sequence_compare_recursive,
-};
-
-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_ctf_field_type_common_structure_compare_recursive,
-};
-
-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_ctf_field_type_common_variant_compare_recursive,
-};
-
-typedef int (*bt_ctf_field_type_serialize_func)(struct bt_ctf_field_type_common *,
- struct metadata_context *);
-
-BT_HIDDEN
-int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
- struct metadata_context *context)
-{
- int ret;
- struct bt_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_ctf_field_type_common_validate((void *) type);
- if (ret) {
- BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
- "addr=%p", type);
- goto end;
- }
-
- serialize_func = type_common->spec.writer.serialize_func;
- ret = serialize_func((void *) type, context);
-
-end:
- return ret;
-}
-
-static
-const char *get_encoding_string(enum bt_ctf_string_encoding encoding)
-{
- const char *encoding_string;
-
- switch (encoding) {
- case BT_CTF_STRING_ENCODING_NONE:
- encoding_string = "none";
- break;
- case BT_CTF_STRING_ENCODING_ASCII:
- encoding_string = "ASCII";
- break;
- case BT_CTF_STRING_ENCODING_UTF8:
- encoding_string = "UTF8";
- break;
- default:
- encoding_string = "unknown";
- break;
- }
-
- return encoding_string;
-}
-
-static
-const char *get_integer_base_string(enum bt_ctf_integer_base base)
-{
- const char *base_string;
-
- switch (base) {
- case BT_CTF_INTEGER_BASE_DECIMAL:
- case BT_CTF_INTEGER_BASE_UNSPECIFIED:
- base_string = "decimal";
- break;
- case BT_CTF_INTEGER_BASE_HEXADECIMAL:
- base_string = "hexadecimal";
- break;
- case BT_CTF_INTEGER_BASE_OCTAL:
- base_string = "octal";
- break;
- case BT_CTF_INTEGER_BASE_BINARY:
- base_string = "binary";
- break;
- default:
- base_string = "unknown";
- break;
- }
-
- return base_string;
-}
-
-static
-void append_field_name(struct metadata_context *context,
- const char *name)
-{
- g_string_append_c(context->string, ' ');
-
- if (!bt_ctf_identifier_is_valid(name) || *name == '_') {
- g_string_append_c(context->string, '_');
- }
-
- g_string_append(context->string, name);
-}
-
-static
-int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- 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: "
- "ft-addr=%p, metadata-context-addr=%p", type, context);
- g_string_append_printf(context->string,
- "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
- integer->size, type->alignment,
- (integer->is_signed ? "true" : "false"),
- get_encoding_string(integer->encoding),
- get_integer_base_string(integer->base),
- bt_ctf_get_byte_order_string(integer->user_byte_order));
- if (integer->mapped_clock_class) {
- const char *clock_name = bt_ctf_clock_class_get_name(
- integer->mapped_clock_class);
-
- BT_ASSERT(clock_name);
- g_string_append_printf(context->string,
- "; map = clock.%s.value", clock_name);
- }
-
- g_string_append(context->string, "; }");
- return ret;
-}
-
-static
-int bt_ctf_field_type_enumeration_serialize_recursive(
- struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- size_t entry;
- int ret;
- 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_ctf_field_type_common_enumeration_borrow_container_field_type(type);
- BT_ASSERT(container_type);
- container_signed = bt_ctf_field_type_common_integer_is_signed(
- container_type);
- BT_ASSERT(container_signed >= 0);
- g_string_append(context->string, "enum : ");
- BT_LOGD_STR("Serializing CTF writer enumeration field type's container field type's metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) enumeration->container_ft, context);
- if (ret) {
- BT_LOGW("Cannot serialize CTF writer enumeration field type's container field type's metadata: "
- "container-ft-addr=%p", enumeration->container_ft);
- goto end;
- }
-
- g_string_append(context->string, " { ");
- for (entry = 0; entry < enumeration->entries->len; entry++) {
- struct 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_ctf_identifier_is_valid(label) || label[0] == '_') {
- g_string_append(context->string, "_");
- }
-
- g_string_append_printf(context->string, "%s\" = ", label);
-
- if (container_signed) {
- if (mapping->range_start._signed ==
- mapping->range_end._signed) {
- g_string_append_printf(context->string,
- "%" PRId64,
- mapping->range_start._signed);
- } else {
- g_string_append_printf(context->string,
- "%" PRId64 " ... %" PRId64,
- mapping->range_start._signed,
- mapping->range_end._signed);
- }
- } else {
- if (mapping->range_start._unsigned ==
- mapping->range_end._unsigned) {
- g_string_append_printf(context->string,
- "%" PRIu64,
- mapping->range_start._unsigned);
- } else {
- g_string_append_printf(context->string,
- "%" PRIu64 " ... %" PRIu64,
- mapping->range_start._unsigned,
- mapping->range_end._unsigned);
- }
- }
-
- g_string_append(context->string,
- ((entry != (enumeration->entries->len - 1)) ?
- ", " : " }"));
- }
-
- if (context->field_name->len) {
- append_field_name(context,
- context->field_name->str);
- g_string_assign(context->field_name, "");
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- 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);
- g_string_append_printf(context->string,
- "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
- floating_point->exp_dig,
- floating_point->mant_dig,
- 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_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- size_t i;
- unsigned int indent;
- int ret = 0;
- 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: "
- "ft-addr=%p, metadata-context-addr=%p", type, context);
- context->field_name = g_string_new("");
-
- context->current_indentation_level++;
- g_string_append(context->string, "struct {\n");
-
- for (i = 0; i < structure->fields->len; i++) {
- struct 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: "
- "index=%zu, "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, field, g_quark_to_string(field->name));
-
- for (indent = 0; indent < context->current_indentation_level;
- indent++) {
- g_string_append_c(context->string, '\t');
- }
-
- g_string_assign(context->field_name,
- g_quark_to_string(field->name));
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) field->type, context);
- if (ret) {
- BT_LOGW("Cannot serialize CTF writer structure field type's field's metadata: "
- "index=%zu, "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, field->type,
- g_quark_to_string(field->name));
- goto end;
- }
-
- if (context->field_name->len) {
- append_field_name(context,
- context->field_name->str);
- }
- g_string_append(context->string, ";\n");
- }
-
- context->current_indentation_level--;
- for (indent = 0; indent < context->current_indentation_level;
- indent++) {
- g_string_append_c(context->string, '\t');
- }
-
- g_string_append_printf(context->string, "} align(%u)",
- type->alignment);
-
-end:
- g_string_free(context->field_name, TRUE);
- context->field_name = structure_field_name;
- return ret;
-}
-
-static
-int bt_ctf_field_type_variant_serialize_recursive(
- struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- size_t i;
- unsigned int indent;
- int ret = 0;
- 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: "
- "ft-addr=%p, metadata-context-addr=%p", type, context);
- context->field_name = g_string_new("");
- if (variant->tag_name->len > 0) {
- g_string_append(context->string, "variant <");
- append_field_name(context, variant->tag_name->str);
- g_string_append(context->string, "> {\n");
- } else {
- g_string_append(context->string, "variant {\n");
- }
-
- context->current_indentation_level++;
- for (i = 0; i < variant->choices->len; i++) {
- 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: "
- "index=%zu, "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, field, g_quark_to_string(field->name));
-
- g_string_assign(context->field_name,
- g_quark_to_string(field->name));
- for (indent = 0; indent < context->current_indentation_level;
- indent++) {
- g_string_append_c(context->string, '\t');
- }
-
- g_string_assign(context->field_name,
- g_quark_to_string(field->name));
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) field->type, context);
- if (ret) {
- BT_LOGW("Cannot serialize CTF writer variant field type's field's metadata: "
- "index=%zu, "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, field->type,
- g_quark_to_string(field->name));
- goto end;
- }
-
- if (context->field_name->len) {
- append_field_name(context,
- context->field_name->str);
- g_string_append_c(context->string, ';');
- }
-
- g_string_append_c(context->string, '\n');
- }
-
- context->current_indentation_level--;
- for (indent = 0; indent < context->current_indentation_level;
- indent++) {
- g_string_append_c(context->string, '\t');
- }
-
- g_string_append(context->string, "}");
-
-end:
- g_string_free(context->field_name, TRUE);
- context->field_name = variant_field_name;
- return ret;
-}
-
-static
-int bt_ctf_field_type_array_serialize_recursive(
- struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- int ret = 0;
- 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);
- BT_LOGD_STR("Serializing CTF writer array field type's element field type's metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) array->element_ft, context);
- if (ret) {
- BT_LOGW("Cannot serialize CTF writer array field type's element field type's metadata: "
- "element-ft-addr=%p", array->element_ft);
- goto end;
- }
-
- if (context->field_name->len) {
- append_field_name(context,
- context->field_name->str);
-
- g_string_append_printf(context->string, "[%u]", array->length);
- g_string_assign(context->field_name, "");
- } else {
- g_string_append_printf(context->string, "[%u]", array->length);
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_type_sequence_serialize_recursive(
- struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- int ret = 0;
- 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);
- BT_LOGD_STR("Serializing CTF writer sequence field type's element field type's metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) sequence->element_ft, context);
- if (ret) {
- BT_LOGW("Cannot serialize CTF writer sequence field type's element field type's metadata: "
- "element-ft-addr=%p", sequence->element_ft);
- goto end;
- }
-
- if (context->field_name->len) {
- append_field_name(context, context->field_name->str);
- g_string_assign(context->field_name, "");
- }
- g_string_append(context->string, "[");
- append_field_name(context, sequence->length_field_name->str);
- g_string_append(context->string, "]");
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type_common *type,
- struct metadata_context *context)
-{
- 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);
- g_string_append_printf(context->string,
- "string { encoding = %s; }",
- get_encoding_string(string->encoding));
- return 0;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
-{
- struct bt_ctf_field_type_common_integer *integer = NULL;
-
- BT_LOGD("Creating CTF writer integer field type object: size=%u", size);
-
- if (size == 0 || size > 64) {
- BT_LOGW("Invalid parameter: size must be between 1 and 64: "
- "size=%u", size);
- goto error;
- }
-
- integer = g_new0(struct bt_ctf_field_type_common_integer, 1);
- if (!integer) {
- BT_LOGE_STR("Failed to allocate one integer field type.");
- goto error;
- }
-
- 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;
- BT_LOGD("Created CTF writer integer field type object: addr=%p, size=%u",
- integer, size);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(integer);
-
-end:
- return (void *) integer;
-}
-
-int bt_ctf_field_type_integer_get_size(struct bt_ctf_field_type *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_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_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_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_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_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_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_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_ctf_object_get_ref(bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
- (void *) ft));
-}
-
-int bt_ctf_field_type_integer_set_mapped_clock_class(
- struct bt_ctf_field_type *ft,
- struct bt_ctf_clock_class *clock_class)
-{
- return bt_ctf_field_type_common_integer_set_mapped_clock_class((void *) ft,
- clock_class);
-}
-
-int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
- struct bt_ctf_field_type *ft, uint64_t index,
- const char **mapping_name, int64_t *range_begin,
- int64_t *range_end)
-{
- return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
- (void *) ft, index, mapping_name, range_begin, range_end);
-}
-
-int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
- struct bt_ctf_field_type *ft, uint64_t index,
- const char **mapping_name, uint64_t *range_begin,
- uint64_t *range_end)
-{
- return bt_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_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);
-
- if (!container_ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- goto error;
- }
-
- 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_ctf_field_type_id_string(int_ft->id));
- goto error;
- }
-
- 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_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;
- BT_LOGD("Created CTF writer enumeration field type object: addr=%p, "
- "int-ft-addr=%p, int-ft-size=%u",
- enumeration, container_ft,
- bt_ctf_field_type_integer_get_size(container_ft));
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(enumeration);
-
-end:
- return (void *) enumeration;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type(
- struct bt_ctf_field_type *ft)
-{
- return bt_ctf_object_get_ref(
- bt_ctf_field_type_common_enumeration_borrow_container_field_type(
- (void *) ft));
-}
-
-int bt_ctf_field_type_enumeration_signed_add_mapping(
- struct bt_ctf_field_type *ft, const char *string,
- int64_t range_start, int64_t range_end)
-{
- return bt_ctf_field_type_common_enumeration_signed_add_mapping(
- (void *) ft, string, range_start, range_end);
-}
-
-int bt_ctf_field_type_enumeration_unsigned_add_mapping(
- struct bt_ctf_field_type *ft, const char *string,
- uint64_t range_start, uint64_t range_end)
-{
- return bt_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_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_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.");
-
- if (!floating_point) {
- BT_LOGE_STR("Failed to allocate one floating point number field type.");
- goto end;
- }
-
- 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;
- BT_LOGD("Created CTF writer floating point number field type object: addr=%p, "
- "exp-size=%u, mant-size=%u", floating_point,
- floating_point->exp_dig, floating_point->mant_dig);
-
-end:
- return (void *) floating_point;
-}
-
-int bt_ctf_field_type_floating_point_get_exponent_digits(
- struct bt_ctf_field_type *ft)
-{
- return bt_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_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_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_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_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.");
-
- if (!structure) {
- BT_LOGE_STR("Failed to allocate one structure field type.");
- goto error;
- }
-
- 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;
- BT_LOGD("Created CTF writer structure field type object: addr=%p",
- structure);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(structure);
-
-end:
- return (void *) structure;
-}
-
-int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *ft,
- struct bt_ctf_field_type *field_type,
- const char *field_name)
-{
- return bt_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_ctf_field_type_common_structure_get_field_count((void *) ft);
-}
-
-int bt_ctf_field_type_structure_get_field_by_index(
- struct bt_ctf_field_type *ft,
- const char **field_name,
- struct bt_ctf_field_type **field_type, uint64_t index)
-{
- 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) {
- bt_ctf_object_get_ref(*field_type);
- }
-
- return ret;
-}
-
-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_ctf_object_get_ref(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_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_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_ctf_field_type_common_variant, 1);
- if (!var_ft) {
- BT_LOGE_STR("Failed to allocate one variant field type.");
- goto error;
- }
-
- bt_ctf_field_type_common_variant_initialize(BT_CTF_TO_COMMON(var_ft),
- (void *) tag_ft, tag_name,
- 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;
- BT_LOGD("Created CTF writer variant field type object: addr=%p, "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- var_ft, tag_ft, tag_name);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(var_ft);
-
-end:
- return (void *) var_ft;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
- struct bt_ctf_field_type *ft)
-{
- return bt_ctf_object_get_ref(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_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_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_ctf_field_type_common_variant_add_field((void *) ft,
- (void *) field_type, field_name);
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_by_name(
- struct bt_ctf_field_type *ft,
- const char *field_name)
-{
- return bt_ctf_object_get_ref(bt_ctf_field_type_common_variant_borrow_field_type_by_name(
- (void *) ft, field_name));
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
- struct bt_ctf_field_type *ft,
- struct bt_ctf_field *tag_field)
-{
- int ret;
- int64_t choice_index;
- struct bt_ctf_field *container;
- 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_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_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_IS_SET((struct bt_ctf_field_common *) tag_field,
- "Tag field");
-
- container = bt_ctf_field_enumeration_borrow_container(tag_field);
- BT_ASSERT(container);
-
- if (var_ft->tag_ft->container_ft->is_signed) {
- int64_t val;
-
- ret = bt_ctf_field_integer_signed_get_value(container,
- &val);
- BT_ASSERT(ret == 0);
- choice_index = bt_ctf_field_type_common_variant_find_choice_index(
- (void *) ft, (uint64_t) val, true);
- } else {
- uint64_t val;
-
- ret = bt_ctf_field_integer_unsigned_get_value(container,
- &val);
- BT_ASSERT(ret == 0);
- 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-addr=%p, tag-field-addr=%p", ft, tag_field);
- goto end;
- }
-
- ret = bt_ctf_field_type_variant_get_field_by_index(ft, NULL,
- &ret_ft, choice_index);
- BT_ASSERT(ret == 0);
-
-end:
- return ret_ft;
-}
-
-int64_t bt_ctf_field_type_variant_get_field_count(struct bt_ctf_field_type *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_ctf_field_type_common_variant_borrow_field_by_index(
- (void *) ft, field_name, (void *) field_type, index);
-
- if (ret == 0 && field_type) {
- bt_ctf_object_get_ref(*field_type);
- }
-
- return ret;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_array_create(
- struct bt_ctf_field_type *element_ft, unsigned int length)
-{
- 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);
-
- if (!element_ft) {
- BT_LOGW_STR("Invalid parameter: element field type is NULL.");
- goto error;
- }
-
- if (length == 0) {
- BT_LOGW_STR("Invalid parameter: length is zero.");
- goto error;
- }
-
- array = g_new0(struct bt_ctf_field_type_common_array, 1);
- if (!array) {
- BT_LOGE_STR("Failed to allocate one array field type.");
- goto error;
- }
-
- bt_ctf_field_type_common_array_initialize(BT_CTF_TO_COMMON(array),
- (void *) element_ft, length,
- 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;
- BT_LOGD("Created CTF writer array field type object: addr=%p, "
- "element-ft-addr=%p, length=%u",
- array, element_ft, length);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(array);
-
-end:
- return (void *) array;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
- struct bt_ctf_field_type *ft)
-{
- return bt_ctf_object_get_ref(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_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_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);
-
- if (!element_ft) {
- BT_LOGW_STR("Invalid parameter: element field type is NULL.");
- goto error;
- }
-
- 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_ctf_field_type_common_sequence, 1);
- if (!sequence) {
- BT_LOGE_STR("Failed to allocate one sequence field type.");
- goto error;
- }
-
- bt_ctf_field_type_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
- (void *) element_ft, length_field_name,
- 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;
- BT_LOGD("Created CTF writer sequence field type object: addr=%p, "
- "element-ft-addr=%p, length-field-name=\"%s\"",
- sequence, element_ft, length_field_name);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(sequence);
-
-end:
- return (void *) sequence;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
- struct bt_ctf_field_type *ft)
-{
- return bt_ctf_object_get_ref(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_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_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.");
-
- if (!string) {
- BT_LOGE_STR("Failed to allocate one string field type.");
- return NULL;
- }
-
- 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;
- BT_LOGD("Created CTF writer string field type object: addr=%p", string);
- return (void *) string;
-}
-
-enum bt_ctf_string_encoding bt_ctf_field_type_string_get_encoding(
- struct bt_ctf_field_type *ft)
-{
- return (int) bt_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_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_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_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_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_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_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_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_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);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer integer field type.");
- goto end;
- }
-
- copy_ft->mapped_clock_class = bt_ctf_object_get_ref(int_ft->mapped_clock_class);
- copy_ft->user_byte_order = int_ft->user_byte_order;
- copy_ft->is_signed = int_ft->is_signed;
- copy_ft->size = int_ft->size;
- copy_ft->base = int_ft->base;
- copy_ft->encoding = int_ft->encoding;
- BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
- struct bt_ctf_field_type *ft)
-{
- size_t i;
- struct bt_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_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;
- }
-
- copy_ft = (void *) bt_ctf_field_type_enumeration_create(
- (void *) container_copy_ft);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
- goto end;
- }
-
- /* Copy all enumaration entries */
- for (i = 0; i < enum_ft->entries->len; i++) {
- struct bt_ctf_enumeration_mapping *mapping = g_ptr_array_index(
- enum_ft->entries, i);
- 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.");
- goto error;
- }
-
- *copy_mapping = *mapping;
- g_ptr_array_add(copy_ft->entries, copy_mapping);
- }
-
- BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_ctf_object_put_ref(container_copy_ft);
- return (void *) copy_ft;
-
-error:
- bt_ctf_object_put_ref(container_copy_ft);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
- return (void *) copy_ft;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
- struct bt_ctf_field_type *ft)
-{
- struct bt_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();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
- goto end;
- }
-
- copy_ft->user_byte_order = flt_ft->user_byte_order;
- copy_ft->exp_dig = flt_ft->exp_dig;
- copy_ft->mant_dig = flt_ft->mant_dig;
- BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
- struct bt_ctf_field_type *ft)
-{
- int64_t i;
- GHashTableIter iter;
- gpointer key, value;
- struct bt_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();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer structure field type.");
- goto end;
- }
-
- /* Copy field_name_to_index */
- g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- g_hash_table_insert(copy_ft->field_name_to_index,
- key, value);
- }
-
- g_array_set_size(copy_ft->fields, struct_ft->fields->len);
-
- for (i = 0; i < struct_ft->fields->len; i++) {
- struct bt_ctf_field_type_common_structure_field *entry, *copy_entry;
- struct bt_ctf_field_type_common *field_ft_copy;
-
- entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
- struct_ft, i);
- 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 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
-
- field_ft_copy = (void *) bt_ctf_field_type_copy(
- (void *) entry->type);
- if (!field_ft_copy) {
- BT_LOGE("Cannot copy CTF writer structure field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
- goto error;
- }
-
- copy_entry->name = entry->name;
- copy_entry->type = field_ft_copy;
- }
-
- BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
- return NULL;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
- struct bt_ctf_field_type *ft)
-{
- int64_t i;
- GHashTableIter iter;
- gpointer key, value;
- struct bt_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_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;
- }
- }
-
- copy_ft = (void *) bt_ctf_field_type_variant_create(
- (void *) tag_ft_copy,
- var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer variant field type.");
- goto end;
- }
-
- /* Copy field_name_to_index */
- g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- g_hash_table_insert(copy_ft->choice_name_to_index,
- key, value);
- }
-
- g_array_set_size(copy_ft->choices, var_ft->choices->len);
-
- for (i = 0; i < var_ft->choices->len; i++) {
- 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_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 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
-
- field_ft_copy = (void *) bt_ctf_field_type_copy(
- (void *) entry->type);
- if (!field_ft_copy) {
- BT_LOGE("Cannot copy CTF writer variant field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
- g_free(copy_entry);
- goto error;
- }
-
- copy_entry->name = entry->name;
- copy_entry->type = field_ft_copy;
-
- /* Copy ranges */
- copy_entry->ranges = g_array_new(FALSE, TRUE,
- 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);
-
- for (range_i = 0; range_i < entry->ranges->len; range_i++) {
- copy_entry->ranges[range_i] = entry->ranges[range_i];
- }
- }
-
- 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_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.");
- goto error;
- }
- }
-
- copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
- BT_LOGD("Copied CTF writer variant field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_ctf_object_put_ref(tag_ft_copy);
- return (void *) copy_ft;
-
-error:
- bt_ctf_object_put_ref(tag_ft_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
- return NULL;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
- struct bt_ctf_field_type *ft)
-{
- struct bt_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_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;
- }
-
- copy_ft = (void *) bt_ctf_field_type_array_create(
- (void *) container_ft_copy, array_ft->length);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer array field type.");
- goto end;
- }
-
- BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_ctf_object_put_ref(container_ft_copy);
- return (void *) copy_ft;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
- struct bt_ctf_field_type *ft)
-{
- struct bt_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_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;
- }
-
- copy_ft = (void *) bt_ctf_field_type_sequence_create(
- (void *) container_ft_copy,
- seq_ft->length_field_name->len ?
- seq_ft->length_field_name->str : NULL);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer sequence field type.");
- goto end;
- }
-
- if (seq_ft->length_field_path) {
- BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
- copy_ft->length_field_path = bt_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.");
- goto error;
- }
- }
-
- BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_ctf_object_put_ref(container_ft_copy);
- return (void *) copy_ft;
-error:
- bt_ctf_object_put_ref(container_ft_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
- return NULL;
-}
-
-static
-struct bt_ctf_field_type *bt_ctf_field_type_string_copy(struct bt_ctf_field_type *ft)
-{
- 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();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create CTF writer string field type.");
- goto end;
- }
-
- copy_ft->encoding = string_ft->encoding;
- BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/object-pool-internal.h>
-#include <babeltrace2/ctf-writer/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_ctf_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_ctf_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_ctf_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;
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-FIELDS"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/align-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compat/fcntl-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctfser-internal.h>
-#include <float.h>
-#include <inttypes.h>
-#include <inttypes.h>
-#include <stdlib.h>
-
-#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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_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_ctf_field_common_generic_is_set,
- .reset = bt_ctf_field_common_generic_reset,
-};
-
-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_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_ctf_field_common *field, bool is_frozen);
-
-static
-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_ctf_field_common *field);
-
-static
-void bt_ctf_field_enumeration_reset_recursive(struct bt_ctf_field_common *field);
-
-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,
- .is_set = bt_ctf_field_enumeration_is_set_recursive,
- .reset = bt_ctf_field_enumeration_reset_recursive,
-};
-
-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_ctf_field_common_generic_is_set,
- .reset = bt_ctf_field_common_generic_reset,
-};
-
-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_ctf_field_common_structure_is_set_recursive,
- .reset = bt_ctf_field_common_structure_reset_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_ctf_field_common_sequence_is_set_recursive,
- .reset = bt_ctf_field_common_sequence_reset_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_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_ctf_field_common *field,
- bool is_frozen);
-
-static
-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_ctf_field_common *field);
-
-static
-void bt_ctf_field_variant_reset_recursive(struct bt_ctf_field_common *field);
-
-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,
- .is_set = bt_ctf_field_variant_is_set_recursive,
- .reset = bt_ctf_field_variant_reset_recursive,
-};
-
-static
-struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_enumeration_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_floating_point_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_structure_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *);
-
-static
-struct bt_ctf_field *(* const field_create_funcs[])(struct bt_ctf_field_type *) = {
- [BT_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_ctf_field_common *, struct bt_ctfser *,
- 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_ctf_field_common_integer_finalize((void *) field);
- g_free(field);
-}
-
-static
-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_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_CTF_FROM_COMMON(field);
-
- BT_LOGD("Destroying CTF writer enumeration field object: addr=%p",
- field);
- BT_LOGD_STR("Putting container field.");
- bt_ctf_object_put_ref(enumeration->container);
- bt_ctf_field_common_finalize((void *) field);
- g_free(field);
-}
-
-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_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_CTF_FROM_COMMON(field);
-
- BT_LOGD("Destroying CTF writer variant field object: addr=%p", field);
- BT_LOGD_STR("Putting tag field.");
- bt_ctf_object_put_ref(variant->tag);
- bt_ctf_field_common_variant_finalize_recursive((void *) field);
- g_free(field);
-}
-
-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_ctf_field_common_array_finalize_recursive((void *) field);
- g_free(field);
-}
-
-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_ctf_field_common_sequence_finalize_recursive((void *) field);
- g_free(field);
-}
-
-static
-void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
-{
- BT_LOGD("Destroying CTF writer string field object: addr=%p", field);
- bt_ctf_field_common_string_finalize((void *) field);
- g_free(field);
-}
-
-BT_HIDDEN
-int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- struct bt_ctf_field_common *field_common = (void *) field;
- bt_ctf_field_serialize_recursive_func serialize_func;
-
- BT_ASSERT(ctfser);
- BT_ASSERT_PRE_NON_NULL(field, "Field");
- BT_ASSERT(field_common->spec.writer.serialize_func);
- serialize_func = field_common->spec.writer.serialize_func;
- return serialize_func(field_common, ctfser,
- native_byte_order);
-}
-
-static
-int bt_ctf_field_integer_serialize(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int ret;
- 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;
-
- BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Integer field");
- BT_LOGV("Serializing CTF writer integer field: addr=%p, native-bo=%s",
- field,
- bt_ctf_byte_order_string(native_byte_order));
- byte_order = int_type->user_byte_order;
- if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- byte_order = native_byte_order;
- }
-
- if (int_type->is_signed) {
- ret = bt_ctfser_write_signed_int(ctfser,
- int_field->payload.signd, int_type->common.alignment,
- int_type->size,
- byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
- LITTLE_ENDIAN : BIG_ENDIAN);
- } else {
- ret = bt_ctfser_write_unsigned_int(ctfser,
- int_field->payload.unsignd, int_type->common.alignment,
- int_type->size,
- byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
- LITTLE_ENDIAN : BIG_ENDIAN);
- }
-
- if (unlikely(ret)) {
- BT_LOGE("Cannot serialize integer field: ret=%d", ret);
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_enumeration_serialize_recursive(
- struct bt_ctf_field_common *field, struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- struct bt_ctf_field_enumeration *enumeration = (void *) field;
-
- BT_LOGV("Serializing enumeration field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string(native_byte_order));
- BT_LOGV_STR("Serializing enumeration field's payload field.");
- return bt_ctf_field_serialize_recursive(
- (void *) enumeration->container, ctfser, native_byte_order);
-}
-
-static
-int bt_ctf_field_floating_point_serialize(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int ret = -1;
- 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;
-
- BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field");
- BT_LOGV("Serializing floating point number field: "
- "addr=%p, native-bo=%s", field,
- bt_ctf_byte_order_string(native_byte_order));
-
- byte_order = flt_type->user_byte_order;
- if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- byte_order = native_byte_order;
- }
-
- if (flt_type->mant_dig == FLT_MANT_DIG) {
- ret = bt_ctfser_write_float32(ctfser, flt_field->payload,
- flt_type->common.alignment,
- byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
- LITTLE_ENDIAN : BIG_ENDIAN);
- } else if (flt_type->mant_dig == DBL_MANT_DIG) {
- ret = bt_ctfser_write_float64(ctfser, flt_field->payload,
- flt_type->common.alignment,
- byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
- LITTLE_ENDIAN : BIG_ENDIAN);
- } else {
- abort();
- }
-
- if (unlikely(ret)) {
- BT_LOGE("Cannot serialize floating point number field: "
- "ret=%d", ret);
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int64_t i;
- int ret;
- struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
-
- BT_LOGV("Serializing structure field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string(native_byte_order));
- ret = bt_ctfser_align_offset_in_current_packet(ctfser,
- field->type->alignment);
- if (unlikely(ret)) {
- BT_LOGE("Cannot align offset before serializing structure field: "
- "ret=%d", ret);
- goto end;
- }
-
- for (i = 0; i < structure->fields->len; i++) {
- struct bt_ctf_field_common *member = g_ptr_array_index(
- structure->fields, i);
- const char *field_name = NULL;
-
- BT_LOGV("Serializing structure field's field: ser-offset=%" PRIu64 ", "
- "field-addr=%p, index=%" PRIu64,
- bt_ctfser_get_offset_in_current_packet_bits(ctfser),
- member, i);
-
- if (unlikely(!member)) {
- 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: "
- "struct-field-addr=%p, "
- "field-name=\"%s\", index=%" PRId64,
- field, field_name, i);
- ret = -1;
- goto end;
- }
-
- ret = bt_ctf_field_serialize_recursive((void *) member, ctfser,
- native_byte_order);
- if (unlikely(ret)) {
- 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: "
- "struct-field-addr=%p, field-addr=%p, "
- "field-name=\"%s\", index=%" PRId64,
- field->type, member, field_name, i);
- break;
- }
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_variant_serialize_recursive(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
-
- BT_LOGV("Serializing variant field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string(native_byte_order));
- BT_LOGV_STR("Serializing variant field's payload field.");
- return bt_ctf_field_serialize_recursive(
- (void *) variant->current_field, ctfser, native_byte_order);
-}
-
-static
-int bt_ctf_field_array_serialize_recursive(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int64_t i;
- int ret = 0;
- struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
-
- BT_LOGV("Serializing array field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string(native_byte_order));
-
- for (i = 0; i < array->elements->len; i++) {
- struct bt_ctf_field_common *elem_field =
- g_ptr_array_index(array->elements, i);
-
- BT_LOGV("Serializing array field's element field: "
- "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
- bt_ctfser_get_offset_in_current_packet_bits(ctfser),
- elem_field, i);
- ret = bt_ctf_field_serialize_recursive(
- (void *) elem_field, ctfser, native_byte_order);
- if (unlikely(ret)) {
- BT_LOGW("Cannot serialize array field's element field: "
- "array-field-addr=%p, field-addr=%p, "
- "index=%" PRId64, field, elem_field, i);
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_sequence_serialize_recursive(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int64_t i;
- int ret = 0;
- struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
-
- BT_LOGV("Serializing sequence field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string(native_byte_order));
-
- for (i = 0; i < sequence->elements->len; i++) {
- struct bt_ctf_field_common *elem_field =
- g_ptr_array_index(sequence->elements, i);
-
- BT_LOGV("Serializing sequence field's element field: "
- "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
- bt_ctfser_get_offset_in_current_packet_bits(ctfser),
- elem_field, i);
- ret = bt_ctf_field_serialize_recursive(
- (void *) elem_field, ctfser, native_byte_order);
- if (unlikely(ret)) {
- BT_LOGW("Cannot serialize sequence field's element field: "
- "sequence-field-addr=%p, field-addr=%p, "
- "index=%" PRId64, field, elem_field, i);
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-static
-int bt_ctf_field_string_serialize(struct bt_ctf_field_common *field,
- struct bt_ctfser *ctfser,
- enum bt_ctf_byte_order native_byte_order)
-{
- int ret;
- struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
-
- BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field");
- BT_LOGV("Serializing string field: addr=%p, native-bo=%s",
- field, bt_ctf_byte_order_string((int) native_byte_order));
- ret = bt_ctfser_write_string(ctfser, (const char *) string->buf->data);
- if (unlikely(ret)) {
- BT_LOGE("Cannot serialize string field: ret=%d", ret);
- goto end;
- }
-
-end:
- return ret;
-}
-
-struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
-{
- struct bt_ctf_field *field = NULL;
- enum bt_ctf_field_type_id type_id;
-
- BT_ASSERT_PRE_NON_NULL(type, "Field type");
- BT_ASSERT(field_type_common_has_known_id((void *) type));
- BT_ASSERT_PRE(bt_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_ctf_field_type_common_freeze((void *) type);
-
-end:
- return field;
-}
-
-struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
-{
- return bt_ctf_object_get_ref(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_ctf_field_common *field_common = (void *) field;
-
- BT_ASSERT_PRE_NON_NULL(field, "Field");
- return (int) field_common->type->id;
-}
-
-int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
- struct bt_ctf_field *length_field)
-{
- int ret;
- 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_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_CTF_FIELD_TYPE_ID_ENUM) {
- struct bt_ctf_field_enumeration *enumeration = (void *)
- length_field;
-
- length_field = (void *) enumeration->container;
- }
-
- ret = bt_ctf_field_integer_unsigned_get_value(length_field, &length);
- BT_ASSERT(ret == 0);
- 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_ctf_object_get_ref(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_ctf_object_get_ref(bt_ctf_field_common_structure_borrow_field_by_name(
- (void *) field, name));
-}
-
-struct bt_ctf_field *bt_ctf_field_array_get_field(
- struct bt_ctf_field *field, uint64_t index)
-{
- return bt_ctf_object_get_ref(
- 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_ctf_object_get_ref(
- 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,
- struct bt_ctf_field *tag_field)
-{
- struct bt_ctf_field_variant *variant_field = (void *) field;
- struct bt_ctf_field_enumeration *enum_field = (void *) tag_field;
- 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;
- int ret;
-
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_NON_NULL(tag_field, "Tag 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_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_CTF_FROM_COMMON(enum_field->common.type);
- is_signed = tag_ft->container_ft->is_signed;
-
- if (is_signed) {
- int64_t tag_ival;
-
- ret = bt_ctf_field_integer_signed_get_value(
- (void *) enum_field->container, &tag_ival);
- tag_uval = (uint64_t) tag_ival;
- } else {
- ret = bt_ctf_field_integer_unsigned_get_value(
- (void *) enum_field->container, &tag_uval);
- }
-
- BT_ASSERT(ret == 0);
- ret = bt_ctf_field_common_variant_set_tag((void *) field, tag_uval,
- is_signed);
- if (ret) {
- goto end;
- }
-
- bt_ctf_object_put_ref(variant_field->tag);
- variant_field->tag = bt_ctf_object_get_ref(tag_field);
- current_field = bt_ctf_field_variant_get_current_field(field);
- BT_ASSERT(current_field);
-
-end:
- return current_field;
-}
-
-struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
- struct bt_ctf_field *variant_field)
-{
- return bt_ctf_object_get_ref(bt_ctf_field_common_variant_borrow_current_field(
- (void *) variant_field));
-}
-
-BT_HIDDEN
-struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
- struct bt_ctf_field *field)
-{
- struct bt_ctf_field_enumeration *enumeration = (void *) field;
-
- BT_ASSERT_PRE_NON_NULL(field, "Enumeration 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;
-}
-
-struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
- struct bt_ctf_field *field)
-{
- return bt_ctf_object_get_ref(bt_ctf_field_enumeration_borrow_container(field));
-}
-
-int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field,
- int64_t *value)
-{
- 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_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: field-addr=%p", field);
- *value = integer->payload.signd;
- return 0;
-}
-
-int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field,
- int64_t value)
-{
- int ret = 0;
- 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_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_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-addr=%p",
- value, field);
- integer->payload.signd = value;
- 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_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_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 signed: field-addr=%p", field);
- *value = integer->payload.unsignd;
- return 0;
-}
-
-int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field,
- uint64_t value)
-{
- 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_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_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-addr=%p",
- value, field);
- integer->payload.unsignd = value;
- 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_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_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_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_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_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_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_ctf_field_common_copy((void *) field);
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type)
-{
- 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_ctf_field_common_initialize(BT_CTF_TO_COMMON(integer), (void *) type,
- true,
- (bt_ctf_object_release_func) bt_ctf_field_integer_destroy,
- &bt_ctf_field_integer_methods);
- integer->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_integer_serialize;
- BT_LOGD("Created CTF writer integer field object: addr=%p, ft-addr=%p",
- integer, type);
- } else {
- BT_LOGE_STR("Failed to allocate one integer field.");
- }
-
- return (void *) integer;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_enumeration_create(
- struct bt_ctf_field_type *type)
-{
- struct bt_ctf_field_type_common_enumeration *enum_ft = (void *) type;
- struct bt_ctf_field_enumeration *enumeration = g_new0(
- struct bt_ctf_field_enumeration, 1);
-
- BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type);
-
- if (!enumeration) {
- BT_LOGE_STR("Failed to allocate one enumeration field.");
- goto end;
- }
-
- bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(enumeration),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_enumeration_destroy_recursive,
- &bt_ctf_field_enumeration_methods);
- enumeration->container = (void *) bt_ctf_field_create(
- BT_CTF_FROM_COMMON(enum_ft->container_ft));
- if (!enumeration->container) {
- BT_CTF_OBJECT_PUT_REF_AND_RESET(enumeration);
- goto end;
- }
-
- enumeration->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func)
- bt_ctf_field_enumeration_serialize_recursive;
- BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
- enumeration, type);
-
-end:
- return (void *) enumeration;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_floating_point_create(
- struct bt_ctf_field_type *type)
-{
- 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_ctf_field_common_floating_point, 1);
-
- if (floating_point) {
- bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(floating_point),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_floating_point_destroy,
- &bt_ctf_field_floating_point_methods);
- floating_point->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_floating_point_serialize;
- BT_LOGD("Created CTF writer floating point number field object: addr=%p, ft-addr=%p",
- floating_point, type);
- } else {
- BT_LOGE_STR("Failed to allocate one floating point number field.");
- }
-
- return (void *) floating_point;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_structure_create(
- struct bt_ctf_field_type *type)
-{
- struct bt_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);
-
- if (!structure) {
- BT_LOGE_STR("Failed to allocate one structure field.");
- goto end;
- }
-
- iret = bt_ctf_field_common_structure_initialize(BT_CTF_TO_COMMON(structure),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_structure_destroy_recursive,
- &bt_ctf_field_structure_methods,
- (bt_ctf_field_common_create_func) bt_ctf_field_create,
- (GDestroyNotify) bt_ctf_object_put_ref);
- structure->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive;
- if (iret) {
- BT_CTF_OBJECT_PUT_REF_AND_RESET(structure);
- goto end;
- }
-
- BT_LOGD("Created CTF writer structure field object: addr=%p, ft-addr=%p",
- structure, type);
-
-end:
- return (void *) structure;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
-{
- struct bt_ctf_field_type_common_variant *var_ft = (void *) type;
- struct bt_ctf_field_variant *variant = g_new0(
- struct bt_ctf_field_variant, 1);
-
- BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type);
-
- if (!variant) {
- BT_LOGE_STR("Failed to allocate one variant field.");
- goto end;
- }
-
- bt_ctf_field_common_variant_initialize(BT_CTF_TO_COMMON(BT_CTF_TO_COMMON(variant)),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_variant_destroy_recursive,
- &bt_ctf_field_variant_methods,
- (bt_ctf_field_common_create_func) bt_ctf_field_create,
- (GDestroyNotify) bt_ctf_object_put_ref);
- variant->tag = (void *) bt_ctf_field_create(
- 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",
- variant, type);
-
-end:
- return (void *) variant;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
-{
- 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);
- BT_ASSERT(type);
-
- if (!array) {
- BT_LOGE_STR("Failed to allocate one array field.");
- goto end;
- }
-
- ret = bt_ctf_field_common_array_initialize(BT_CTF_TO_COMMON(array),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_array_destroy_recursive,
- &bt_ctf_field_array_methods,
- (bt_ctf_field_common_create_func) bt_ctf_field_create,
- (GDestroyNotify) bt_ctf_object_put_ref);
- array->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive;
- if (ret) {
- BT_CTF_OBJECT_PUT_REF_AND_RESET(array);
- goto end;
- }
-
- BT_LOGD("Created CTF writer array field object: addr=%p, ft-addr=%p",
- array, type);
-
-end:
- return (void *) array;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type)
-{
- struct bt_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_ctf_field_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_sequence_destroy_recursive,
- &bt_ctf_field_sequence_methods,
- (GDestroyNotify) bt_ctf_object_put_ref);
- sequence->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_sequence_serialize_recursive;
- BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p",
- sequence, type);
- } else {
- BT_LOGE_STR("Failed to allocate one sequence field.");
- }
-
- return (void *) sequence;
-}
-
-static
-struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
-{
- struct bt_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_ctf_field_common_string_initialize(BT_CTF_TO_COMMON(string),
- (void *) type,
- true, (bt_ctf_object_release_func)
- bt_ctf_field_string_destroy,
- &bt_ctf_field_string_methods);
- string->common.spec.writer.serialize_func =
- (bt_ctf_field_serialize_recursive_func) bt_ctf_field_string_serialize;
- BT_LOGD("Created CTF writer string field object: addr=%p, ft-addr=%p",
- string, type);
- } else {
- BT_LOGE_STR("Failed to allocate one string field.");
- }
-
- return (void *) string;
-}
-
-static
-void bt_ctf_field_enumeration_set_is_frozen_recursive(
- struct bt_ctf_field_common *field, bool is_frozen)
-{
- struct bt_ctf_field_enumeration *enumeration = (void *) field;
-
- if (enumeration->container) {
- bt_ctf_field_common_set_is_frozen_recursive(
- (void *) enumeration->container, is_frozen);
- }
-
- bt_ctf_field_common_generic_set_is_frozen((void *) field, is_frozen);
-}
-
-static
-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_ctf_field_common_validate_recursive(
- (void *) enumeration->container);
- }
-
- return ret;
-}
-
-static
-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_ctf_field_common_is_set_recursive(
- (void *) enumeration->container);
- }
-
- return is_set;
-}
-
-static
-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_ctf_field_common_reset_recursive(
- (void *) enumeration->container);
- }
-
- bt_ctf_field_common_generic_reset((void *) field);
-}
-
-static
-void bt_ctf_field_variant_set_is_frozen_recursive(
- struct bt_ctf_field_common *field, bool is_frozen)
-{
- struct bt_ctf_field_variant *variant = (void *) field;
-
- if (variant->tag) {
- bt_ctf_field_common_set_is_frozen_recursive(
- (void *) variant->tag, is_frozen);
- }
-
- bt_ctf_field_common_variant_set_is_frozen_recursive((void *) field,
- is_frozen);
-}
-
-static
-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_ctf_field_common_validate_recursive(
- (void *) variant->tag);
- if (ret) {
- goto end;
- }
- }
-
- 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_ctf_field_common *field)
-{
- bt_bool is_set;
- struct bt_ctf_field_variant *variant = (void *) field;
-
- if (variant->tag) {
- is_set = bt_ctf_field_common_is_set_recursive(
- (void *) variant->tag);
- if (is_set) {
- goto end;
- }
- }
-
- 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_ctf_field_common *field)
-{
- struct bt_ctf_field_variant *variant = (void *) field;
-
- if (variant->tag) {
- bt_ctf_field_common_reset_recursive(
- (void *) variant->tag);
- }
-
- bt_ctf_field_common_variant_reset_recursive((void *) field);
-}
-
-BT_ASSERT_PRE_FUNC
-static inline bool field_to_set_has_expected_type(
- struct bt_ctf_field_common *struct_field,
- const char *name, struct bt_ctf_field_common *value)
-{
- bool ret = true;
- struct bt_ctf_field_type_common *expected_field_type = NULL;
-
- expected_field_type =
- bt_ctf_field_type_common_structure_borrow_field_type_by_name(
- struct_field->type, name);
-
- 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-addr=%p, expected-ft-addr=%p", value->type,
- expected_field_type);
- ret = false;
- goto end;
- }
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
- const char *name, struct bt_ctf_field *value)
-{
- int ret = 0;
- GQuark field_quark;
- 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_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_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_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,
- (gpointer *) &index)) {
- BT_LOGV("Invalid parameter: no such field in structure field's type: "
- "struct-field-addr=%p, struct-ft-addr=%p, "
- "field-ft-addr=%p, name=\"%s\"",
- field, common_field->type, common_value->type, name);
- ret = -1;
- goto end;
- }
- bt_ctf_object_get_ref(value);
- BT_CTF_OBJECT_MOVE_REF(structure->fields->pdata[index], value);
-
-end:
- return ret;
-}
+++ /dev/null
-/*
- * functor.c
- *
- * Babeltrace CTF Writer
- *
- * 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 <glib.h>
-#include <babeltrace2/ctf-writer/functor-internal.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-
-BT_HIDDEN
-void value_exists(gpointer element, gpointer search_query)
-{
- if (element == ((struct bt_ctf_search_query *)search_query)->value) {
- ((struct bt_ctf_search_query *)search_query)->found = 1;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
- * Copyright (c) 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 "OBJECT-POOL"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <stdint.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/ctf-writer/object-pool-internal.h>
-
-int bt_ctf_object_pool_initialize(struct bt_ctf_object_pool *pool,
- bt_ctf_object_pool_new_object_func new_object_func,
- bt_ctf_object_pool_destroy_object_func destroy_object_func,
- void *data)
-{
- int ret = 0;
-
- BT_ASSERT(new_object_func);
- BT_ASSERT(destroy_object_func);
- BT_LOGD("Initializing object pool: addr=%p, data-addr=%p",
- pool, data);
- pool->objects = g_ptr_array_new();
- if (!pool->objects) {
- BT_LOGE_STR("Failed to allocate a GPtrArray.");
- goto error;
- }
-
- pool->funcs.new_object = new_object_func;
- pool->funcs.destroy_object = destroy_object_func;
- pool->data = data;
- pool->size = 0;
- BT_LIB_LOGD("Initialized object pool: %!+o", pool);
- goto end;
-
-error:
- if (pool) {
- bt_ctf_object_pool_finalize(pool);
- }
-
- ret = -1;
-
-end:
- return ret;
-}
-
-void bt_ctf_object_pool_finalize(struct bt_ctf_object_pool *pool)
-{
- uint64_t i;
-
- BT_ASSERT(pool);
- BT_LIB_LOGD("Finalizing object pool: %!+o", pool);
-
- if (pool->objects) {
- for (i = 0; i < pool->size; i++) {
- void *obj = pool->objects->pdata[i];
-
- if (obj) {
- pool->funcs.destroy_object(obj, pool->data);
- }
- }
-
- g_ptr_array_free(pool->objects, TRUE);
- pool->objects = NULL;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 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 <babeltrace2/ctf-writer/object-internal.h>
-
-void *bt_ctf_object_get_ref(void *obj)
-{
- if (unlikely(!obj)) {
- goto end;
- }
-
- bt_ctf_object_get_no_null_check(obj);
-
-end:
- return obj;
-}
-
-void bt_ctf_object_put_ref(void *obj)
-{
- if (unlikely(!obj)) {
- return;
- }
-
- bt_ctf_object_put_no_null_check(obj);
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/babeltrace-internal.h>
-#include <babeltrace2/ctf-writer/field-path-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/resolve-internal.h>
-#include <babeltrace2/ctf-writer/stream-class.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/types.h>
-#include <babeltrace2/ctf-writer/values-internal.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_ctf_private_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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(child_type);
- BT_CTF_OBJECT_MOVE_REF(type, child_type);
- }
-
-end:
- bt_ctf_object_put_ref(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(child_type);
- BT_CTF_OBJECT_MOVE_REF(type, child_type);
- }
-
- return type;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_PUT_REF_AND_RESET(target_field_path);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_private_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;
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-STREAM-CLASS"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/align-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/event-internal.h>
-#include <babeltrace2/ctf-writer/event.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/trace.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/validation-internal.h>
-#include <babeltrace2/ctf-writer/visitor-internal.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object.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_ctf_object_release_func release_func)
-{
- BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
-
- bt_ctf_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_ctf_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_ctf_object_put_ref(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_ctf_object_put_ref(stream_class->event_header_field_type);
- BT_LOGD_STR("Putting packet context field type.");
- bt_ctf_object_put_ref(stream_class->packet_context_field_type);
- BT_LOGD_STR("Putting event context field type.");
- bt_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_CTF_OBJECT_MOVE_REF(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_ctf_object_put_ref(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 = bt_ctf_visitor_helper(&obj, get_event_class_count,
- get_event_class,
- visit_event_class, visitor, data);
- BT_LOGV("bt_ctf_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)
-{
- int ret = 0;
- struct bt_ctf_field_type *event_header_type =
- bt_ctf_field_type_structure_create();
- struct bt_ctf_field_type *_uint32_t =
- get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
- struct bt_ctf_field_type *_uint64_t =
- get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
-
- if (!event_header_type) {
- BT_LOGE_STR("Cannot create empty structure field type.");
- ret = -1;
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(event_header_type,
- _uint32_t, "id");
- if (ret) {
- BT_LOGE_STR("Cannot add `id` field to event header field type.");
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(event_header_type,
- _uint64_t, "timestamp");
- if (ret) {
- BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
- goto end;
- }
-
- bt_ctf_object_put_ref(stream_class->common.event_header_field_type);
- stream_class->common.event_header_field_type =
- (void *) event_header_type;
- event_header_type = NULL;
-
-end:
- if (ret) {
- bt_ctf_object_put_ref(event_header_type);
- }
-
- bt_ctf_object_put_ref(_uint32_t);
- bt_ctf_object_put_ref(_uint64_t);
- return ret;
-}
-
-static
-int init_packet_context(struct bt_ctf_stream_class *stream_class)
-{
- int ret = 0;
- struct bt_ctf_field_type *packet_context_type =
- bt_ctf_field_type_structure_create();
- struct bt_ctf_field_type *_uint64_t =
- get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
- struct bt_ctf_field_type *ts_begin_end_uint64_t;
-
- if (!packet_context_type) {
- BT_LOGE_STR("Cannot create empty structure field type.");
- ret = -1;
- goto end;
- }
-
- ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
- if (!ts_begin_end_uint64_t) {
- BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
- ret = -1;
- goto end;
- }
-
- /*
- * We create a stream packet context as proposed in the CTF
- * specification.
- */
- ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- ts_begin_end_uint64_t, "timestamp_begin");
- if (ret) {
- BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- ts_begin_end_uint64_t, "timestamp_end");
- if (ret) {
- BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- _uint64_t, "content_size");
- if (ret) {
- BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- _uint64_t, "packet_size");
- if (ret) {
- BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(packet_context_type,
- _uint64_t, "events_discarded");
- if (ret) {
- BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
- goto end;
- }
-
- bt_ctf_object_put_ref(stream_class->common.packet_context_field_type);
- stream_class->common.packet_context_field_type =
- (void *) packet_context_type;
- packet_context_type = NULL;
-
-end:
- if (ret) {
- bt_ctf_object_put_ref(packet_context_type);
- goto end;
- }
-
- bt_ctf_object_put_ref(_uint64_t);
- bt_ctf_object_put_ref(ts_begin_end_uint64_t);
- return ret;
-}
-
-static
-void bt_ctf_stream_class_destroy(struct bt_ctf_object *obj)
-{
- struct bt_ctf_stream_class *stream_class;
-
- stream_class = (void *) obj;
- BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class));
- bt_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class));
- bt_ctf_object_put_ref(stream_class->clock);
- g_free(stream_class);
-}
-
-struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
-{
- struct bt_ctf_stream_class *stream_class;
- int ret;
-
- BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name);
- stream_class = g_new0(struct bt_ctf_stream_class, 1);
- if (!stream_class) {
- BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
- goto error;
- }
-
- ret = bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class),
- name, bt_ctf_stream_class_destroy);
- if (ret) {
- /* bt_ctf_stream_class_common_initialize() logs errors */
- goto error;
- }
-
- ret = init_event_header(stream_class);
- if (ret) {
- BT_LOGE_STR("Cannot initialize stream class's event header field type.");
- goto error;
- }
-
- ret = init_packet_context(stream_class);
- if (ret) {
- BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
- goto error;
- }
-
- BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
- stream_class, name);
- return stream_class;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_class);
- return stream_class;
-}
-
-static
-int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
- struct bt_ctf_field_type *parent_ft, const char *field_name)
-{
- struct bt_ctf_clock_class *mapped_clock_class = NULL;
- int ret = 0;
- struct bt_ctf_field_type *ft =
- bt_ctf_field_type_structure_get_field_type_by_name(parent_ft,
- field_name);
-
- BT_ASSERT(stream_class->clock);
-
- if (!ft) {
- /* Field does not exist: not an error */
- goto end;
- }
-
- BT_ASSERT(((struct bt_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) {
- struct bt_ctf_field_type *ft_copy;
-
- if (!stream_class->clock) {
- BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", ft-addr=%p",
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class), ft);
- ret = -1;
- goto end;
- }
-
- ft_copy = bt_ctf_field_type_copy(ft);
- if (!ft_copy) {
- BT_LOGE("Failed to copy integer field type: ft-addr=%p",
- ft);
- }
-
- ret = bt_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_ctf_field_type_common_structure_replace_field(
- (void *) parent_ft, field_name, (void *) ft_copy);
- bt_ctf_object_put_ref(ft_copy);
- BT_LOGV("Automatically mapped field type to stream class's clock class: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", ft-addr=%p, "
- "ft-copy-addr=%p",
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
- }
-
-end:
- bt_ctf_object_put_ref(ft);
- bt_ctf_object_put_ref(mapped_clock_class);
- return ret;
-}
-
-BT_HIDDEN
-int bt_ctf_stream_class_map_clock_class(
- struct bt_ctf_stream_class *stream_class,
- struct bt_ctf_field_type *packet_context_type,
- struct bt_ctf_field_type *event_header_type)
-{
- int ret = 0;
-
- BT_ASSERT(stream_class);
-
- if (!stream_class->clock) {
- /* No clock class to map to */
- goto end;
- }
-
- if (packet_context_type) {
- if (try_map_clock_class(stream_class, packet_context_type,
- "timestamp_begin")) {
- BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
- ret = -1;
- goto end;
- }
-
- if (try_map_clock_class(stream_class, packet_context_type,
- "timestamp_end")) {
- BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
- ret = -1;
- goto end;
- }
- }
-
- if (event_header_type) {
- if (try_map_clock_class(stream_class, event_header_type,
- "timestamp")) {
- BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
- ret = -1;
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
- struct bt_ctf_stream_class *stream_class)
-{
- struct bt_ctf_clock *clock = NULL;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
-
- if (!stream_class->clock) {
- BT_LOGV("Stream class has no clock: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class));
- goto end;
- }
-
- clock = bt_ctf_object_get_ref(stream_class->clock);
-
-end:
- return clock;
-}
-
-int bt_ctf_stream_class_set_clock(
- struct bt_ctf_stream_class *stream_class,
- struct bt_ctf_clock *clock)
-{
- int ret = 0;
-
- if (!stream_class || !clock) {
- BT_LOGW("Invalid parameter: stream class or clock is NULL: "
- "stream-class-addr=%p, clock-addr=%p",
- stream_class, clock);
- ret = -1;
- goto end;
- }
-
- if (stream_class->common.frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class));
- ret = -1;
- goto end;
- }
-
- /* Replace the current clock of this stream class. */
- bt_ctf_object_put_ref(stream_class->clock);
- stream_class->clock = bt_ctf_object_get_ref(clock);
- BT_LOGV("Set stream class's clock: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "clock-addr=%p, clock-name=\"%s\"",
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class),
- stream_class->clock,
- bt_ctf_clock_get_name(stream_class->clock));
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
- struct metadata_context *context)
-{
- int ret = 0;
- size_t i;
- struct bt_ctf_trace *trace;
- struct bt_ctf_field_type *packet_header_type = NULL;
-
- BT_LOGD("Serializing stream class's metadata: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
- stream_class,
- bt_ctf_stream_class_get_name(stream_class),
- bt_ctf_stream_class_get_id(stream_class), context);
- g_string_assign(context->field_name, "");
- context->current_indentation_level = 1;
- if (!stream_class->common.id_set) {
- BT_LOGW_STR("Stream class's ID is not set.");
- ret = -1;
- goto end;
- }
-
- g_string_append(context->string, "stream {\n");
-
- /*
- * The reference to the trace is only borrowed since the
- * serialization of the stream class might have been triggered
- * by the trace's destruction. In such a case, the trace's
- * reference count would, unexepectedly, go through the sequence
- * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
- * and serialization.
- */
- trace = BT_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;
- if (packet_header_type) {
- struct bt_ctf_field_type *stream_id_type;
-
- stream_id_type =
- bt_ctf_field_type_structure_get_field_type_by_name(
- packet_header_type, "stream_id");
- if (stream_id_type) {
- /*
- * Only set the stream's id if the trace's packet header
- * contains a stream_id field. This field is only
- * needed if the trace contains only one stream
- * class.
- */
- g_string_append_printf(context->string,
- "\tid = %" PRId64 ";\n",
- stream_class->common.id);
- }
- bt_ctf_object_put_ref(stream_id_type);
- }
- if (stream_class->common.event_header_field_type) {
- BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
- g_string_append(context->string, "\tevent.header := ");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) stream_class->common.event_header_field_type,
- context);
- if (ret) {
- BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
- "ret=%d", ret);
- goto end;
- }
- g_string_append(context->string, ";");
- }
-
-
- if (stream_class->common.packet_context_field_type) {
- BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
- g_string_append(context->string, "\n\n\tpacket.context := ");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) stream_class->common.packet_context_field_type,
- context);
- if (ret) {
- BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
- "ret=%d", ret);
- goto end;
- }
- g_string_append(context->string, ";");
- }
-
- if (stream_class->common.event_context_field_type) {
- BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
- g_string_append(context->string, "\n\n\tevent.context := ");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) stream_class->common.event_context_field_type,
- context);
- if (ret) {
- BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
- "ret=%d", ret);
- goto end;
- }
- g_string_append(context->string, ";");
- }
-
- g_string_append(context->string, "\n};\n\n");
-
- for (i = 0; i < stream_class->common.event_classes->len; i++) {
- struct bt_ctf_event_class *event_class =
- stream_class->common.event_classes->pdata[i];
-
- ret = bt_ctf_event_class_serialize(event_class, context);
- if (ret) {
- BT_LOGW("Cannot serialize event class's metadata: "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- event_class,
- bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class));
- goto end;
- }
- }
-
-end:
- bt_ctf_object_put_ref(packet_header_type);
- context->current_indentation_level = 0;
- return ret;
-}
-
-struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
- struct bt_ctf_stream_class *stream_class)
-{
- return bt_ctf_object_get_ref(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_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_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_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_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_ctf_object_get_ref(
- 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_ctf_stream_class_common_set_packet_context_field_type(
- BT_CTF_TO_COMMON(stream_class), (void *) packet_context_type);
-}
-
-struct bt_ctf_field_type *
-bt_ctf_stream_class_get_event_header_type(
- struct bt_ctf_stream_class *stream_class)
-{
- return bt_ctf_object_get_ref(
- 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_ctf_stream_class_common_set_event_header_field_type(
- BT_CTF_TO_COMMON(stream_class), (void *) event_header_type);
-}
-
-struct bt_ctf_field_type *
-bt_ctf_stream_class_get_event_context_type(
- struct bt_ctf_stream_class *stream_class)
-{
- return bt_ctf_object_get_ref(
- 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_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_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_ctf_object_get_ref(
- 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_ctf_object_get_ref(
- 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_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);
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-STREAM"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/align-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/event-internal.h>
-#include <babeltrace2/ctf-writer/field-types.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/stream-class.h>
-#include <babeltrace2/ctf-writer/stream-internal.h>
-#include <babeltrace2/ctf-writer/stream.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/trace.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctfser-internal.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_ctf_object_release_func release_func)
-{
- int ret = 0;
- struct bt_ctf_trace_common *trace = NULL;
-
- bt_ctf_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_ctf_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_ctf_object *obj);
-
-static
-int try_set_structure_field_integer(struct bt_ctf_field *, char *, uint64_t);
-
-static
-int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
-{
- int ret = 0;
- struct bt_ctf_field_type *field_type = NULL;
-
- if (!field) {
- BT_LOGW_STR("Invalid parameter: field is NULL.");
- ret = -1;
- goto end;
- }
-
- field_type = bt_ctf_field_get_type(field);
- BT_ASSERT(field_type);
-
- if (bt_ctf_field_type_get_type_id(field_type) !=
- BT_CTF_FIELD_TYPE_ID_INTEGER) {
- /* Not an integer and the value is unset, error. */
- BT_LOGW("Invalid parameter: field's type is not an integer field type: "
- "field-addr=%p, ft-addr=%p, ft-id=%s",
- field, field_type,
- bt_ctf_field_type_id_string((int)
- bt_ctf_field_type_get_type_id(field_type)));
- ret = -1;
- goto end;
- }
-
- if (bt_ctf_field_type_integer_is_signed(field_type)) {
- ret = bt_ctf_field_integer_signed_set_value(field, (int64_t) value);
- if (ret) {
- /* Value is out of range, error. */
- BT_LOGW("Cannot set signed integer field's value: "
- "addr=%p, value=%" PRId64,
- field, (int64_t) value);
- goto end;
- }
- } else {
- ret = bt_ctf_field_integer_unsigned_set_value(field, value);
- if (ret) {
- /* Value is out of range, error. */
- BT_LOGW("Cannot set unsigned integer field's value: "
- "addr=%p, value=%" PRIu64,
- field, value);
- goto end;
- }
- }
-end:
- bt_ctf_object_put_ref(field_type);
- return ret;
-}
-
-static
-int set_packet_header_magic(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_header, "magic");
- const uint32_t magic_value = 0xc1fc1fc1;
-
- BT_ASSERT(stream);
-
- if (!magic_field) {
- /* No magic field found. Not an error, skip. */
- BT_LOGV("No field named `magic` in packet header: skipping: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- ret = bt_ctf_field_integer_unsigned_set_value(magic_field,
- (uint64_t) magic_value);
-
- if (ret) {
- BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- magic_field, (uint64_t) magic_value);
- } else {
- BT_LOGV("Set packet header field's `magic` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- magic_field, (uint64_t) magic_value);
- }
-end:
- bt_ctf_object_put_ref(magic_field);
- return ret;
-}
-
-static
-int set_packet_header_uuid(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- int64_t i;
- struct bt_ctf_trace *trace = NULL;
- struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_header, "uuid");
-
- BT_ASSERT(stream);
-
- if (!uuid_field) {
- /* No uuid field found. Not an error, skip. */
- BT_LOGV("No field named `uuid` in packet header: skipping: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- trace = (struct bt_ctf_trace *)
- bt_ctf_object_get_parent(&stream->common.base);
-
- for (i = 0; i < 16; i++) {
- struct bt_ctf_field *uuid_element =
- bt_ctf_field_array_get_field(uuid_field, i);
-
- ret = bt_ctf_field_integer_unsigned_set_value(
- uuid_element, (uint64_t) trace->common.uuid[i]);
- bt_ctf_object_put_ref(uuid_element);
- if (ret) {
- BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
- "value=%" PRIu64 ", index=%" PRId64,
- stream, bt_ctf_stream_get_name(stream),
- uuid_element, (uint64_t) trace->common.uuid[i], i);
- goto end;
- }
- }
-
- BT_LOGV("Set packet header field's `uuid` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
- stream, bt_ctf_stream_get_name(stream), uuid_field);
-
-end:
- bt_ctf_object_put_ref(uuid_field);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
- return ret;
-}
-static
-int set_packet_header_stream_id(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- uint32_t stream_id;
- struct bt_ctf_field *stream_id_field =
- bt_ctf_field_structure_get_field_by_name(
- stream->packet_header, "stream_id");
-
- if (!stream_id_field) {
- /* No stream_id field found. Not an error, skip. */
- BT_LOGV("No field named `stream_id` in packet header: skipping: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- stream_id = stream->common.stream_class->id;
- ret = bt_ctf_field_integer_unsigned_set_value(stream_id_field,
- (uint64_t) stream_id);
- if (ret) {
- BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- stream_id_field, (uint64_t) stream_id);
- } else {
- BT_LOGV("Set packet header field's `stream_id` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- stream_id_field, (uint64_t) stream_id);
- }
-
-end:
- bt_ctf_object_put_ref(stream_id_field);
- return ret;
-}
-
-static
-int auto_populate_packet_header(struct bt_ctf_stream *stream)
-{
- int ret = 0;
-
- if (!stream->packet_header) {
- goto end;
- }
-
- ret = set_packet_header_magic(stream);
- if (ret) {
- BT_LOGW("Cannot set packet header's magic number field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- ret = set_packet_header_uuid(stream);
- if (ret) {
- BT_LOGW("Cannot set packet header's UUID field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- ret = set_packet_header_stream_id(stream);
- if (ret) {
- BT_LOGW("Cannot set packet header's stream class ID field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- BT_LOGV("Automatically populated stream's packet header's known fields: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
-
-end:
- return ret;
-}
-
-static
-int set_packet_context_packet_size(struct bt_ctf_stream *stream,
- uint64_t packet_size_bits)
-{
- int ret = 0;
- struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "packet_size");
-
- ret = bt_ctf_field_integer_unsigned_set_value(field, packet_size_bits);
- if (ret) {
- BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, packet_size_bits);
- } else {
- BT_LOGV("Set packet context field's `packet_size` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, packet_size_bits);
- }
-
- bt_ctf_object_put_ref(field);
- return ret;
-}
-
-static
-int set_packet_context_content_size(struct bt_ctf_stream *stream,
- uint64_t content_size_bits)
-{
- int ret = 0;
- struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "content_size");
-
- BT_ASSERT(stream);
-
- if (!field) {
- /* No content size field found. Not an error, skip. */
- BT_LOGV("No field named `content_size` in packet context: skipping: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- ret = bt_ctf_field_integer_unsigned_set_value(field, content_size_bits);
- if (ret) {
- BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, content_size_bits);
- } else {
- BT_LOGV("Set packet context field's `content_size` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, content_size_bits);
- }
-
-end:
- bt_ctf_object_put_ref(field);
- return ret;
-}
-
-static
-int set_packet_context_events_discarded(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "events_discarded");
-
- BT_ASSERT(stream);
-
- if (!field) {
- /* No discarded events count field found. Not an error, skip. */
- BT_LOGV("No field named `events_discarded` in packet context: skipping: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- /*
- * If the field is set by the user, make sure that the value is
- * greater than or equal to the stream's current count of
- * discarded events. We do not allow wrapping here. If it's
- * valid, update the stream's current count.
- */
- if (bt_ctf_field_is_set_recursive(field)) {
- uint64_t user_val;
-
- ret = bt_ctf_field_integer_unsigned_get_value(field,
- &user_val);
- if (ret) {
- BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
- stream, bt_ctf_stream_get_name(stream), field);
- goto end;
- }
-
- if (user_val < stream->discarded_events) {
- BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
- "value is lesser than the stream's current discarded events count: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
- "value=%" PRIu64 ", "
- "stream-discarded-events-count=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream), field,
- user_val, stream->discarded_events);
- goto end;
- }
-
- stream->discarded_events = user_val;
- } else {
- ret = bt_ctf_field_integer_unsigned_set_value(field,
- stream->discarded_events);
- if (ret) {
- BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, stream->discarded_events);
- } else {
- BT_LOGV("Set packet context field's `events_discarded` field's value: "
- "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- field, stream->discarded_events);
- }
- }
-
-end:
- bt_ctf_object_put_ref(field);
- return ret;
-}
-
-static
-void update_clock_value(uint64_t *val, uint64_t new_val,
- unsigned int new_val_size)
-{
- const uint64_t pow2 = 1ULL << new_val_size;
- const uint64_t mask = pow2 - 1;
- uint64_t val_masked;
-
-#ifdef BT_LOG_ENABLED_VERBOSE
- uint64_t old_val = *val;
-#endif
-
- if (new_val_size == 64) {
- *val = new_val;
- goto end;
- }
-
- val_masked = *val & mask;
-
- if (new_val < val_masked) {
- /* Wrapped once */
- new_val |= pow2;
- }
-
- *val &= ~mask;
- *val |= new_val;
-
-end:
- BT_LOGV("Updated clock value: old-val=%" PRIu64 ", new-val=%" PRIu64,
- old_val, *val);
- return;
-}
-
-static
-int visit_field_update_clock_value(struct bt_ctf_field *field, uint64_t *val)
-{
- int ret = 0;
- struct bt_ctf_field_common *field_common = (void *) field;
-
- if (!field) {
- goto end;
- }
-
- switch (bt_ctf_field_get_type_id(field)) {
- case BT_CTF_FIELD_TYPE_ID_INTEGER:
- {
- struct bt_ctf_clock_class *cc =
- bt_ctf_field_type_integer_get_mapped_clock_class(
- (void *) field_common->type);
- int val_size;
- uint64_t uval;
-
- if (!cc) {
- goto end;
- }
-
- bt_ctf_object_put_ref(cc);
- val_size = bt_ctf_field_type_integer_get_size(
- (void *) field_common->type);
- BT_ASSERT(val_size >= 1);
-
- if (bt_ctf_field_type_integer_is_signed(
- (void *) field_common->type)) {
- int64_t ival;
-
- ret = bt_ctf_field_integer_signed_get_value(field, &ival);
- uval = (uint64_t) ival;
- } else {
- ret = bt_ctf_field_integer_unsigned_get_value(field, &uval);
- }
-
- if (ret) {
- /* Not set */
- goto end;
- }
-
- update_clock_value(val, uval, val_size);
- break;
- }
- case BT_CTF_FIELD_TYPE_ID_ENUM:
- {
- struct bt_ctf_field *int_field =
- bt_ctf_field_enumeration_get_container(field);
-
- BT_ASSERT(int_field);
- ret = visit_field_update_clock_value(int_field, val);
- bt_ctf_object_put_ref(int_field);
- break;
- }
- case BT_CTF_FIELD_TYPE_ID_ARRAY:
- {
- uint64_t i;
- int64_t len = bt_ctf_field_type_array_get_length(
- (void *) field_common->type);
-
- BT_ASSERT(len >= 0);
-
- for (i = 0; i < len; i++) {
- struct bt_ctf_field *elem_field =
- bt_ctf_field_array_get_field(field, i);
-
- BT_ASSERT(elem_field);
- ret = visit_field_update_clock_value(elem_field, val);
- bt_ctf_object_put_ref(elem_field);
- if (ret) {
- goto end;
- }
- }
- break;
- }
- case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
- {
- uint64_t i;
- int64_t len = bt_ctf_field_common_sequence_get_length(
- (void *) field);
-
- if (len < 0) {
- ret = -1;
- goto end;
- }
-
- for (i = 0; i < len; i++) {
- struct bt_ctf_field *elem_field =
- bt_ctf_field_sequence_get_field(field, i);
-
- BT_ASSERT(elem_field);
- ret = visit_field_update_clock_value(elem_field, val);
- bt_ctf_object_put_ref(elem_field);
- if (ret) {
- goto end;
- }
- }
- break;
- }
- case BT_CTF_FIELD_TYPE_ID_STRUCT:
- {
- uint64_t i;
- int64_t len = bt_ctf_field_type_structure_get_field_count(
- (void *) field_common->type);
-
- BT_ASSERT(len >= 0);
-
- for (i = 0; i < len; i++) {
- struct bt_ctf_field *member_field =
- bt_ctf_field_structure_get_field_by_index(field, i);
-
- BT_ASSERT(member_field);
- ret = visit_field_update_clock_value(member_field, val);
- bt_ctf_object_put_ref(member_field);
- if (ret) {
- goto end;
- }
- }
- break;
- }
- case BT_CTF_FIELD_TYPE_ID_VARIANT:
- {
- struct bt_ctf_field *cur_field =
- bt_ctf_field_variant_get_current_field(field);
-
- if (!cur_field) {
- ret = -1;
- goto end;
- }
-
- ret = visit_field_update_clock_value(cur_field, val);
- bt_ctf_object_put_ref(cur_field);
- break;
- }
- default:
- break;
- }
-
-end:
- return ret;
-}
-
-int visit_event_update_clock_value(struct bt_ctf_event *event, uint64_t *val)
-{
- int ret = 0;
- struct bt_ctf_field *field;
-
- field = bt_ctf_event_get_header(event);
- ret = visit_field_update_clock_value(field, val);
- bt_ctf_object_put_ref(field);
- if (ret) {
- BT_LOGW_STR("Cannot automatically update clock value in "
- "event's header.");
- goto end;
- }
-
- field = bt_ctf_event_get_stream_event_context(event);
- ret = visit_field_update_clock_value(field, val);
- bt_ctf_object_put_ref(field);
- if (ret) {
- BT_LOGW_STR("Cannot automatically update clock value in "
- "event's stream event context.");
- goto end;
- }
-
- field = bt_ctf_event_get_context(event);
- ret = visit_field_update_clock_value(field, val);
- bt_ctf_object_put_ref(field);
- if (ret) {
- BT_LOGW_STR("Cannot automatically update clock value in "
- "event's context.");
- goto end;
- }
-
- field = bt_ctf_event_get_payload_field(event);
- ret = visit_field_update_clock_value(field, val);
- bt_ctf_object_put_ref(field);
- if (ret) {
- BT_LOGW_STR("Cannot automatically update clock value in "
- "event's payload.");
- goto end;
- }
-
-end:
- return ret;
-}
-
-static
-int set_packet_context_timestamps(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- uint64_t val;
- uint64_t cur_clock_value;
- uint64_t init_clock_value = 0;
- struct bt_ctf_field *ts_begin_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "timestamp_begin");
- struct bt_ctf_field *ts_end_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "timestamp_end");
- struct bt_ctf_field_common *packet_context =
- (void *) stream->packet_context;
- uint64_t i;
- int64_t len;
-
- if (ts_begin_field && bt_ctf_field_is_set_recursive(ts_begin_field)) {
- /* Use provided `timestamp_begin` value as starting value */
- ret = bt_ctf_field_integer_unsigned_get_value(ts_begin_field, &val);
- BT_ASSERT(ret == 0);
- init_clock_value = val;
- } else if (stream->last_ts_end != -1ULL) {
- /* Use last packet's ending timestamp as starting value */
- init_clock_value = stream->last_ts_end;
- }
-
- cur_clock_value = init_clock_value;
-
- if (stream->last_ts_end != -1ULL &&
- cur_clock_value < stream->last_ts_end) {
- BT_LOGW("Packet's initial timestamp is less than previous "
- "packet's final timestamp: "
- "stream-addr=%p, stream-name=\"%s\", "
- "cur-packet-ts-begin=%" PRIu64 ", "
- "prev-packet-ts-end=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- cur_clock_value, stream->last_ts_end);
- ret = -1;
- goto end;
- }
-
- /*
- * Visit all the packet context fields, followed by all the
- * fields of all the events, in order, updating our current
- * clock value as we visit.
- *
- * While visiting the packet context fields, do not consider
- * `timestamp_begin` and `timestamp_end` because this function's
- * purpose is to set them anyway. Also do not consider
- * `packet_size`, `content_size`, `events_discarded`, and
- * `packet_seq_num` if they are not set because those are
- * autopopulating fields.
- */
- len = bt_ctf_field_type_structure_get_field_count(
- (void *) packet_context->type);
- BT_ASSERT(len >= 0);
-
- for (i = 0; i < len; i++) {
- const char *member_name;
- struct bt_ctf_field *member_field;
-
- ret = bt_ctf_field_type_structure_get_field_by_index(
- (void *) packet_context->type, &member_name, NULL, i);
- BT_ASSERT(ret == 0);
-
- if (strcmp(member_name, "timestamp_begin") == 0 ||
- strcmp(member_name, "timestamp_end") == 0) {
- continue;
- }
-
- member_field = bt_ctf_field_structure_get_field_by_index(
- stream->packet_context, i);
- BT_ASSERT(member_field);
-
- if (strcmp(member_name, "packet_size") == 0 &&
- !bt_ctf_field_is_set_recursive(member_field)) {
- bt_ctf_object_put_ref(member_field);
- continue;
- }
-
- if (strcmp(member_name, "content_size") == 0 &&
- !bt_ctf_field_is_set_recursive(member_field)) {
- bt_ctf_object_put_ref(member_field);
- continue;
- }
-
- if (strcmp(member_name, "events_discarded") == 0 &&
- !bt_ctf_field_is_set_recursive(member_field)) {
- bt_ctf_object_put_ref(member_field);
- continue;
- }
-
- if (strcmp(member_name, "packet_seq_num") == 0 &&
- !bt_ctf_field_is_set_recursive(member_field)) {
- bt_ctf_object_put_ref(member_field);
- continue;
- }
-
- ret = visit_field_update_clock_value(member_field,
- &cur_clock_value);
- bt_ctf_object_put_ref(member_field);
- if (ret) {
- BT_LOGW("Cannot automatically update clock value "
- "in stream's packet context: "
- "stream-addr=%p, stream-name=\"%s\", "
- "field-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream),
- member_name);
- goto end;
- }
- }
-
- for (i = 0; i < stream->events->len; i++) {
- struct bt_ctf_event *event = g_ptr_array_index(stream->events, i);
-
- BT_ASSERT(event);
- ret = visit_event_update_clock_value(event, &cur_clock_value);
- if (ret) {
- BT_LOGW("Cannot automatically update clock value "
- "in stream's packet context: "
- "stream-addr=%p, stream-name=\"%s\", "
- "index=%" PRIu64 ", event-addr=%p, "
- "event-class-id=%" PRId64 ", "
- "event-class-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream),
- i, event,
- bt_ctf_event_class_common_get_id(event->common.class),
- bt_ctf_event_class_common_get_name(event->common.class));
- goto end;
- }
- }
-
- /*
- * Everything is visited, thus the current clock value
- * corresponds to the ending timestamp. Validate this value
- * against the provided value of `timestamp_end`, if any,
- * otherwise set it.
- */
- if (ts_end_field && bt_ctf_field_is_set_recursive(ts_end_field)) {
- ret = bt_ctf_field_integer_unsigned_get_value(ts_end_field, &val);
- BT_ASSERT(ret == 0);
-
- if (val < cur_clock_value) {
- BT_LOGW("Packet's final timestamp is less than "
- "computed packet's final timestamp: "
- "stream-addr=%p, stream-name=\"%s\", "
- "cur-packet-ts-end=%" PRIu64 ", "
- "computed-packet-ts-end=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream),
- val, cur_clock_value);
- ret = -1;
- goto end;
- }
-
- stream->last_ts_end = val;
- }
-
- if (ts_end_field && !bt_ctf_field_is_set_recursive(ts_end_field)) {
- ret = set_integer_field_value(ts_end_field, cur_clock_value);
- BT_ASSERT(ret == 0);
- stream->last_ts_end = cur_clock_value;
- }
-
- if (!ts_end_field) {
- stream->last_ts_end = cur_clock_value;
- }
-
- /* Set `timestamp_begin` field to initial clock value */
- if (ts_begin_field && !bt_ctf_field_is_set_recursive(ts_begin_field)) {
- ret = set_integer_field_value(ts_begin_field, init_clock_value);
- BT_ASSERT(ret == 0);
- }
-
-end:
- bt_ctf_object_put_ref(ts_begin_field);
- bt_ctf_object_put_ref(ts_end_field);
- return ret;
-}
-
-static
-int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts,
- uint64_t packet_size_bits, uint64_t content_size_bits)
-{
- int ret = 0;
-
- if (!stream->packet_context) {
- goto end;
- }
-
- ret = set_packet_context_packet_size(stream, packet_size_bits);
- if (ret) {
- BT_LOGW("Cannot set packet context's packet size field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- ret = set_packet_context_content_size(stream, content_size_bits);
- if (ret) {
- BT_LOGW("Cannot set packet context's content size field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- if (set_ts) {
- ret = set_packet_context_timestamps(stream);
- if (ret) {
- BT_LOGW("Cannot set packet context's timestamp fields: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
- }
-
- ret = set_packet_context_events_discarded(stream);
- if (ret) {
- BT_LOGW("Cannot set packet context's discarded events count field: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
- goto end;
- }
-
- BT_LOGV("Automatically populated stream's packet context's known fields: "
- "stream-addr=%p, stream-name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
-
-end:
- return ret;
-}
-
-static
-void release_event(struct bt_ctf_event *event)
-{
- if (bt_ctf_object_get_ref_count(&event->common.base)) {
- /*
- * The event is being orphaned, but it must guarantee the
- * existence of its event class for the duration of its
- * lifetime.
- */
- bt_ctf_object_get_ref(event->common.class);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(event->common.base.parent);
- } else {
- bt_ctf_object_try_spec_release(&event->common.base);
- }
-}
-
-static
-int create_stream_file(struct bt_ctf_writer *writer,
- struct bt_ctf_stream *stream)
-{
- int ret = 0;
- GString *filename = g_string_new(NULL);
- int64_t stream_class_id;
- char *file_path = NULL;
-
- BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
- "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
- writer, stream, bt_ctf_stream_get_name(stream),
- stream->common.stream_class,
- stream->common.stream_class->name->str);
-
- if (stream->common.name && stream->common.name->len > 0) {
- /* Use stream name's base name as prefix */
- gchar *basename = g_path_get_basename(stream->common.name->str);
-
- BT_ASSERT(basename);
-
- if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
- g_string_assign(filename, "stream");
- } else {
- g_string_assign(filename, basename);
- }
-
- g_free(basename);
- goto append_ids;
- }
-
- if (stream->common.stream_class->name &&
- stream->common.stream_class->name->len > 0) {
- /* Use stream class name's base name as prefix */
- gchar *basename =
- g_path_get_basename(
- stream->common.stream_class->name->str);
-
- BT_ASSERT(basename);
-
- if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
- g_string_assign(filename, "stream");
- } else {
- g_string_assign(filename, basename);
- }
-
- g_free(basename);
- goto append_ids;
- }
-
- /* Default to using `stream-` as prefix */
- g_string_assign(filename, "stream");
-
-append_ids:
- stream_class_id = bt_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,
- stream_class_id, stream->common.id);
-
- file_path = g_build_filename(writer->path->str, filename->str, NULL);
- if (file_path == NULL) {
- ret = -1;
- goto end;
- }
-
- ret = bt_ctfser_init(&stream->ctfser, file_path);
- g_free(file_path);
- if (ret) {
- /* bt_ctfser_init() logs errors */
- goto end;
- }
-
- BT_LOGD("Created stream file for writing: "
- "stream-addr=%p, stream-name=\"%s\", "
- "filename=\"%s\"", stream, bt_ctf_stream_get_name(stream),
- filename->str);
-
-end:
- g_string_free(filename, TRUE);
- return ret;
-}
-
-BT_HIDDEN
-struct bt_ctf_stream *bt_ctf_stream_create_with_id(
- struct bt_ctf_stream_class *stream_class,
- const char *name, uint64_t id)
-{
- int ret;
- int fd;
- struct bt_ctf_stream *stream = NULL;
- struct bt_ctf_trace *trace = NULL;
- struct bt_ctf_writer *writer = NULL;
-
- BT_LOGD("Creating CTF writer stream object: stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-name=\"%s\", "
- "stream-id=%" PRIu64,
- stream_class, bt_ctf_stream_class_get_name(stream_class),
- name, id);
- stream = g_new0(struct bt_ctf_stream, 1);
- if (!stream) {
- BT_LOGE_STR("Failed to allocate one stream.");
- goto error;
- }
-
- if (id == -1ULL) {
- id = stream_class->next_stream_id;
- }
-
- ret = bt_ctf_stream_common_initialize(BT_CTF_TO_COMMON(stream),
- BT_CTF_TO_COMMON(stream_class), name, id, bt_ctf_stream_destroy);
- if (ret) {
- /* bt_ctf_stream_common_initialize() logs errors */
- goto error;
- }
-
- 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\", "
- "stream-name=\"%s\"",
- stream_class, bt_ctf_stream_class_get_name(stream_class),
- name);
- goto error;
- }
-
- writer = (struct bt_ctf_writer *)
- bt_ctf_object_get_parent(&trace->common.base);
- stream->last_ts_end = -1ULL;
- BT_LOGD("CTF writer stream object belongs writer's trace: "
- "writer-addr=%p", writer);
- BT_ASSERT(writer);
-
- if (stream_class->common.packet_context_field_type) {
- BT_LOGD("Creating stream's packet context field: "
- "ft-addr=%p",
- stream_class->common.packet_context_field_type);
- stream->packet_context = bt_ctf_field_create(
- (void *) stream_class->common.packet_context_field_type);
- if (!stream->packet_context) {
- BT_LOGW_STR("Cannot create stream's packet context field.");
- goto error;
- }
-
- /* Initialize events_discarded */
- ret = try_set_structure_field_integer(
- stream->packet_context, "events_discarded", 0);
- if (ret < 0) {
- BT_LOGW("Cannot set `events_discarded` field in packet context: "
- "ret=%d, packet-context-field-addr=%p",
- ret, stream->packet_context);
- goto error;
- }
- }
-
- stream->events = g_ptr_array_new_with_free_func(
- (GDestroyNotify) release_event);
- if (!stream->events) {
- BT_LOGE_STR("Failed to allocate a GPtrArray.");
- goto error;
- }
-
- if (trace->common.packet_header_field_type) {
- BT_LOGD("Creating stream's packet header field: "
- "ft-addr=%p", trace->common.packet_header_field_type);
- stream->packet_header =
- bt_ctf_field_create(
- (void *) trace->common.packet_header_field_type);
- if (!stream->packet_header) {
- BT_LOGW_STR("Cannot create stream's packet header field.");
- goto error;
- }
- }
-
- /*
- * Attempt to populate the default trace packet header fields
- * (magic, uuid and stream_id). This will _not_ fail shall the
- * fields not be found or be of an incompatible type; they will
- * simply not be populated automatically. The user will have to
- * make sure to set the trace packet header fields himself
- * before flushing.
- */
- ret = auto_populate_packet_header(stream);
- if (ret) {
- BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
- goto error;
- }
-
- /* Create file associated with this stream */
- fd = create_stream_file(writer, stream);
- if (fd < 0) {
- BT_LOGW_STR("Cannot create stream file.");
- goto error;
- }
-
- /* Freeze the writer */
- BT_LOGD_STR("Freezing stream's CTF writer.");
- bt_ctf_writer_freeze(writer);
-
- /* Add this stream to the trace's streams */
- g_ptr_array_add(trace->common.streams, stream);
- stream_class->next_stream_id++;
- BT_LOGD("Created stream object: addr=%p", stream);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(stream);
-
-end:
- bt_ctf_object_put_ref(writer);
- return stream;
-}
-
-struct bt_ctf_stream *bt_ctf_stream_create(
- struct bt_ctf_stream_class *stream_class,
- const char *name, uint64_t id_param)
-{
- return bt_ctf_stream_create_with_id(stream_class,
- name, id_param);
-}
-
-int bt_ctf_stream_get_discarded_events_count(
- struct bt_ctf_stream *stream, uint64_t *count)
-{
- int ret = 0;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = -1;
- goto end;
- }
-
- if (!count) {
- BT_LOGW_STR("Invalid parameter: count is NULL.");
- ret = -1;
- goto end;
- }
-
- *count = (uint64_t) stream->discarded_events;
-
-end:
- return ret;
-}
-
-static
-int set_packet_context_events_discarded_field(struct bt_ctf_stream *stream,
- uint64_t count)
-{
- int ret = 0;
- struct bt_ctf_field *events_discarded_field = NULL;
-
- if (!stream->packet_context) {
- goto end;
- }
-
- events_discarded_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "events_discarded");
- if (!events_discarded_field) {
- goto end;
- }
-
- ret = bt_ctf_field_integer_unsigned_set_value(
- events_discarded_field, count);
- if (ret) {
- BT_LOGW("Cannot set packet context's `events_discarded` field: "
- "field-addr=%p, value=%" PRIu64,
- events_discarded_field, count);
- goto end;
- }
-
-end:
- bt_ctf_object_put_ref(events_discarded_field);
- return ret;
-}
-
-void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
- uint64_t event_count)
-{
- int ret;
- uint64_t new_count;
- struct bt_ctf_field *events_discarded_field = NULL;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- goto end;
- }
-
- BT_LOGV("Appending discarded events to stream: "
- "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream), event_count);
-
- if (!stream->packet_context) {
- BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
- goto end;
- }
-
- events_discarded_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "events_discarded");
- if (!events_discarded_field) {
- BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
- goto end;
- }
-
- new_count = stream->discarded_events + event_count;
- if (new_count < stream->discarded_events) {
- BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
- "cur-count=%" PRIu64 ", new-count=%" PRIu64,
- stream->discarded_events, new_count);
- goto end;
- }
-
- ret = set_packet_context_events_discarded_field(stream, new_count);
- if (ret) {
- /* set_packet_context_events_discarded_field() logs errors */
- goto end;
- }
-
- stream->discarded_events = new_count;
- BT_LOGV("Appended discarded events to stream: "
- "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
- stream, bt_ctf_stream_get_name(stream), event_count);
-
-end:
- bt_ctf_object_put_ref(events_discarded_field);
-}
-
-static int auto_populate_event_header(struct bt_ctf_stream *stream,
- struct bt_ctf_event *event)
-{
- int ret = 0;
- struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
- struct bt_ctf_clock_class *mapped_clock_class = NULL;
- struct bt_ctf_stream_class *stream_class =
- BT_CTF_FROM_COMMON(bt_ctf_stream_common_borrow_class(
- BT_CTF_TO_COMMON(stream)));
- int64_t event_class_id;
-
- BT_ASSERT(event);
-
- if (!event->common.header_field) {
- goto end;
- }
-
- if (event->common.frozen) {
- BT_LOGW_STR("Cannot populate event header field: event is frozen.");
- ret = -1;
- goto end;
- }
-
- BT_LOGV("Automatically populating event's header field: "
- "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
- stream, bt_ctf_stream_get_name(stream), event);
-
- id_field = bt_ctf_field_structure_get_field_by_name(
- (void *) event->common.header_field->field, "id");
- 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) {
- ret = set_integer_field_value(id_field, event_class_id);
- if (ret) {
- BT_LOGW("Cannot set event header's `id` field's value: "
- "addr=%p, value=%" PRIu64, id_field,
- event_class_id);
- goto end;
- }
- }
-
- /*
- * The conditions to automatically set the timestamp are:
- *
- * 1. The event header field "timestamp" exists and is an
- * integer field.
- * 2. This stream's class has a registered clock (set with
- * bt_ctf_stream_class_set_clock()).
- * 3. The "timestamp" field is not set.
- */
- timestamp_field = bt_ctf_field_structure_get_field_by_name(
- (void *) event->common.header_field->field, "timestamp");
- if (timestamp_field && stream_class->clock &&
- bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER &&
- !bt_ctf_field_is_set_recursive(timestamp_field)) {
- mapped_clock_class =
- bt_ctf_field_type_integer_get_mapped_clock_class(
- (void *) ((struct bt_ctf_field_common *) timestamp_field)->type);
- if (mapped_clock_class) {
- uint64_t timestamp;
-
- BT_ASSERT(mapped_clock_class ==
- stream_class->clock->clock_class);
- ret = bt_ctf_clock_get_value(
- stream_class->clock,
- ×tamp);
- BT_ASSERT(ret == 0);
- ret = set_integer_field_value(timestamp_field,
- timestamp);
- if (ret) {
- BT_LOGW("Cannot set event header's `timestamp` field's value: "
- "addr=%p, value=%" PRIu64,
- timestamp_field, timestamp);
- goto end;
- }
- }
- }
-
- BT_LOGV("Automatically populated event's header field: "
- "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
- stream, bt_ctf_stream_get_name(stream), event);
-
-end:
- bt_ctf_object_put_ref(id_field);
- bt_ctf_object_put_ref(timestamp_field);
- bt_ctf_object_put_ref(mapped_clock_class);
- return ret;
-}
-
-int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
- struct bt_ctf_event *event)
-{
- int ret = 0;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = -1;
- goto end;
- }
-
- if (!event) {
- BT_LOGW_STR("Invalid parameter: event is NULL.");
- ret = -1;
- goto end;
- }
-
- BT_LOGV("Appending event to stream: "
- "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- stream, bt_ctf_stream_get_name(stream), event,
- bt_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
- * point. The only other way an event can have a parent stream
- * is if it was assigned when setting a packet to the event,
- * in which case the packet's stream is not a writer stream,
- * and thus the user is trying to append an event which belongs
- * to another stream.
- */
- if (event->common.base.parent) {
- ret = -1;
- goto end;
- }
-
- bt_ctf_object_set_parent(&event->common.base, &stream->common.base);
- BT_LOGV_STR("Automatically populating the header of the event to append.");
- ret = auto_populate_event_header(stream, event);
- if (ret) {
- /* auto_populate_event_header() reports errors */
- goto error;
- }
-
- /* Make sure the various scopes of the event are set */
- BT_LOGV_STR("Validating event to append.");
- 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_ctf_event_common_set_is_frozen(BT_CTF_TO_COMMON(event), true);
- g_ptr_array_add(stream->events, event);
-
- /*
- * Event had to hold a reference to its event class as long as it wasn't
- * part of the same trace hierarchy. From now on, the event and its
- * class share the same lifetime guarantees and the reference is no
- * longer needed.
- */
- BT_LOGV_STR("Putting the event's class.");
- bt_ctf_object_put_ref(event->common.class);
- BT_LOGV("Appended event to stream: "
- "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- stream, bt_ctf_stream_get_name(stream), event,
- bt_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;
-
-error:
- /*
- * Orphan the event; we were not successful in associating it to
- * a stream.
- */
- bt_ctf_object_set_parent(&event->common.base, NULL);
- return ret;
-}
-
-struct bt_ctf_field *bt_ctf_stream_get_packet_context(struct bt_ctf_stream *stream)
-{
- struct bt_ctf_field *packet_context = NULL;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- goto end;
- }
-
- packet_context = stream->packet_context;
- if (packet_context) {
- bt_ctf_object_get_ref(packet_context);
- }
-end:
- return packet_context;
-}
-
-int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
- struct bt_ctf_field *field)
-{
- int ret = 0;
- struct bt_ctf_field_type *field_type;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = -1;
- goto end;
- }
-
- field_type = bt_ctf_field_get_type(field);
- 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\", "
- "packet-context-field-addr=%p, "
- "packet-context-ft-addr=%p",
- stream, bt_ctf_stream_get_name(stream),
- field, field_type);
- ret = -1;
- goto end;
- }
-
- bt_ctf_object_put_ref(field_type);
- bt_ctf_object_put_ref(stream->packet_context);
- stream->packet_context = bt_ctf_object_get_ref(field);
- BT_LOGV("Set stream's packet context field: "
- "stream-addr=%p, stream-name=\"%s\", "
- "packet-context-field-addr=%p",
- stream, bt_ctf_stream_get_name(stream), field);
-end:
- return ret;
-}
-
-struct bt_ctf_field *bt_ctf_stream_get_packet_header(struct bt_ctf_stream *stream)
-{
- struct bt_ctf_field *packet_header = NULL;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- goto end;
- }
-
- packet_header = stream->packet_header;
- if (packet_header) {
- bt_ctf_object_get_ref(packet_header);
- }
-end:
- return packet_header;
-}
-
-int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
- struct bt_ctf_field *field)
-{
- int ret = 0;
- struct bt_ctf_trace *trace = NULL;
- struct bt_ctf_field_type *field_type = NULL;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = -1;
- goto end;
- }
-
- trace = (struct bt_ctf_trace *)
- bt_ctf_object_get_parent(&stream->common.base);
-
- if (!field) {
- if (trace->common.packet_header_field_type) {
- BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
- "stream-addr=%p, stream-name=\"%s\", "
- "packet-header-field-addr=%p, "
- "expected-ft-addr=%p",
- stream, bt_ctf_stream_get_name(stream),
- field, trace->common.packet_header_field_type);
- ret = -1;
- goto end;
- }
-
- goto skip_validation;
- }
-
- field_type = bt_ctf_field_get_type(field);
- BT_ASSERT(field_type);
-
- if (bt_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\", "
- "packet-header-field-addr=%p, "
- "packet-header-ft-addr=%p",
- stream, bt_ctf_stream_get_name(stream),
- field, field_type);
- ret = -1;
- goto end;
- }
-
-skip_validation:
- bt_ctf_object_put_ref(stream->packet_header);
- stream->packet_header = bt_ctf_object_get_ref(field);
- BT_LOGV("Set stream's packet header field: "
- "stream-addr=%p, stream-name=\"%s\", "
- "packet-header-field-addr=%p",
- stream, bt_ctf_stream_get_name(stream), field);
-end:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
- bt_ctf_object_put_ref(field_type);
- return ret;
-}
-
-static
-void reset_structure_field(struct bt_ctf_field *structure, const char *name)
-{
- struct bt_ctf_field *member;
-
- member = bt_ctf_field_structure_get_field_by_name(structure, name);
- if (member) {
- bt_ctf_field_common_reset_recursive((void *) member);
- bt_ctf_object_put_ref(member);
- }
-}
-
-int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
-{
- int ret = 0;
- size_t i;
- uint64_t packet_context_offset_bits = 0;
- struct bt_ctf_trace *trace;
- enum bt_ctf_byte_order native_byte_order;
- bool has_packet_size = false;
- uint64_t packet_size_bits = 0;
- uint64_t content_size_bits = 0;
-
- if (!stream) {
- BT_LOGW_STR("Invalid parameter: stream is NULL.");
- ret = -1;
- goto end_no_stream;
- }
-
- if (stream->packet_context) {
- struct bt_ctf_field *packet_size_field;
-
- packet_size_field = bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "packet_size");
- has_packet_size = (packet_size_field != NULL);
- bt_ctf_object_put_ref(packet_size_field);
- }
-
- if (stream->flushed_packet_count == 1) {
- if (!stream->packet_context) {
- BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
- ret = -1;
- goto end;
- }
-
- if (!has_packet_size) {
- BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
- ret = -1;
- goto end;
- }
- }
-
- BT_LOGV("Flushing stream's current packet: stream-addr=%p, "
- "stream-name=\"%s\", packet-index=%u", stream,
- bt_ctf_stream_get_name(stream), stream->flushed_packet_count);
- trace = BT_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);
-
- ret = auto_populate_packet_header(stream);
- if (ret) {
- BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
- ret = -1;
- goto end;
- }
-
- /* Initialize packet/content sizes to `0`; we will overwrite later */
- ret = auto_populate_packet_context(stream, true, 0, 0);
- if (ret) {
- BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
- ret = -1;
- goto end;
- }
-
- ret = bt_ctfser_open_packet(&stream->ctfser);
- if (ret) {
- /* bt_ctfser_open_packet() logs errors */
- ret = -1;
- goto end;
- }
-
- if (stream->packet_header) {
- BT_LOGV_STR("Serializing packet header field (initial).");
- ret = bt_ctf_field_serialize_recursive(stream->packet_header,
- &stream->ctfser, native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize stream's packet header field: "
- "field-addr=%p", stream->packet_header);
- goto end;
- }
- }
-
- if (stream->packet_context) {
- /* Save packet context's position to overwrite it later */
- packet_context_offset_bits =
- bt_ctfser_get_offset_in_current_packet_bits(
- &stream->ctfser);
-
- /* Write packet context */
- BT_LOGV_STR("Serializing packet context field (initial).");
- ret = bt_ctf_field_serialize_recursive(stream->packet_context,
- &stream->ctfser, native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize stream's packet context field: "
- "field-addr=%p", stream->packet_context);
- goto end;
- }
- }
-
- BT_LOGV("Serializing events: count=%u", stream->events->len);
-
- for (i = 0; i < stream->events->len; i++) {
- struct bt_ctf_event *event = g_ptr_array_index(
- stream->events, i);
- struct bt_ctf_event_class *event_class =
- BT_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 ", "
- "ser-offset=%" PRIu64,
- i, event, bt_ctf_event_class_get_name(event_class),
- bt_ctf_event_class_get_id(event_class),
- bt_ctfser_get_offset_in_current_packet_bits(
- &stream->ctfser));
-
- /* Write event header */
- if (event->common.header_field) {
- BT_LOGV_STR("Serializing event's header field.");
- ret = bt_ctf_field_serialize_recursive(
- (void *) event->common.header_field->field,
- &stream->ctfser, native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize event's header field: "
- "field-addr=%p",
- event->common.header_field->field);
- goto end;
- }
- }
-
- /* Write stream event context */
- if (event->common.stream_event_context_field) {
- BT_LOGV_STR("Serializing event's stream event context field.");
- ret = bt_ctf_field_serialize_recursive(
- (void *) event->common.stream_event_context_field,
- &stream->ctfser, native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize event's stream event context field: "
- "field-addr=%p",
- event->common.stream_event_context_field);
- goto end;
- }
- }
-
- /* Write event content */
- ret = bt_ctf_event_serialize(event, &stream->ctfser,
- native_byte_order);
- if (ret) {
- /* bt_ctf_event_serialize() logs errors */
- goto end;
- }
- }
-
- content_size_bits = bt_ctfser_get_offset_in_current_packet_bits(
- &stream->ctfser);
-
- if (!has_packet_size && content_size_bits % 8 != 0) {
- BT_LOGW("Stream's packet context field type has no `packet_size` field, "
- "but current content size is not a multiple of 8 bits: "
- "content-size=%" PRIu64 ", "
- "packet-size=%" PRIu64,
- content_size_bits,
- packet_size_bits);
- ret = -1;
- goto end;
- }
-
- /* Set packet size; make it a multiple of 8 */
- packet_size_bits = (content_size_bits + 7) & ~UINT64_C(7);
-
- if (stream->packet_context) {
- /*
- * The whole packet is serialized at this point. Make
- * sure that, if `packet_size` is missing, the current
- * content size is equal to the current packet size.
- */
- struct bt_ctf_field *field =
- bt_ctf_field_structure_get_field_by_name(
- stream->packet_context, "content_size");
-
- bt_ctf_object_put_ref(field);
- if (!field) {
- if (content_size_bits != packet_size_bits) {
- BT_LOGW("Stream's packet context's `content_size` field is missing, "
- "but current packet's content size is not equal to its packet size: "
- "content-size=%" PRIu64 ", "
- "packet-size=%" PRIu64,
- bt_ctfser_get_offset_in_current_packet_bits(&stream->ctfser),
- packet_size_bits);
- ret = -1;
- goto end;
- }
- }
-
- /*
- * Overwrite the packet context now that the stream
- * position's packet and content sizes have the correct
- * values.
- */
- bt_ctfser_set_offset_in_current_packet_bits(&stream->ctfser,
- packet_context_offset_bits);
- ret = auto_populate_packet_context(stream, false,
- packet_size_bits, content_size_bits);
- if (ret) {
- BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
- ret = -1;
- goto end;
- }
-
- BT_LOGV("Rewriting (serializing) packet context field.");
- ret = bt_ctf_field_serialize_recursive(stream->packet_context,
- &stream->ctfser, native_byte_order);
- if (ret) {
- BT_LOGW("Cannot serialize stream's packet context field: "
- "field-addr=%p", stream->packet_context);
- goto end;
- }
- }
-
- g_ptr_array_set_size(stream->events, 0);
- stream->flushed_packet_count++;
- bt_ctfser_close_current_packet(&stream->ctfser, packet_size_bits / 8);
-
-end:
- /* Reset automatically-set fields. */
- if (stream->packet_context) {
- reset_structure_field(stream->packet_context, "timestamp_begin");
- reset_structure_field(stream->packet_context, "timestamp_end");
- reset_structure_field(stream->packet_context, "packet_size");
- reset_structure_field(stream->packet_context, "content_size");
- reset_structure_field(stream->packet_context, "events_discarded");
- }
-
- if (ret == 0) {
- BT_LOGV("Flushed stream's current packet: "
- "content-size=%" PRIu64 ", packet-size=%" PRIu64,
- content_size_bits, packet_size_bits);
- }
-
-end_no_stream:
- return ret;
-}
-
-static
-void bt_ctf_stream_destroy(struct bt_ctf_object *obj)
-{
- struct bt_ctf_stream *stream = (void *) obj;
-
- BT_LOGD("Destroying CTF writer stream object: addr=%p, name=\"%s\"",
- stream, bt_ctf_stream_get_name(stream));
-
- bt_ctf_stream_common_finalize(BT_CTF_TO_COMMON(stream));
- bt_ctfser_fini(&stream->ctfser);
-
- if (stream->events) {
- BT_LOGD_STR("Putting events.");
- g_ptr_array_free(stream->events, TRUE);
- }
-
- BT_LOGD_STR("Putting packet header field.");
- bt_ctf_object_put_ref(stream->packet_header);
- BT_LOGD_STR("Putting packet context field.");
- bt_ctf_object_put_ref(stream->packet_context);
- g_free(stream);
-}
-
-static
-int _set_structure_field_integer(struct bt_ctf_field *structure, char *name,
- uint64_t value, bt_bool force)
-{
- int ret = 0;
- struct bt_ctf_field_type *field_type = NULL;
- struct bt_ctf_field *integer;
-
- BT_ASSERT(structure);
- BT_ASSERT(name);
-
- integer = bt_ctf_field_structure_get_field_by_name(structure, name);
- if (!integer) {
- /* Field not found, not an error. */
- BT_LOGV("Field not found: struct-field-addr=%p, "
- "name=\"%s\", force=%d", structure, name, force);
- goto end;
- }
-
- /* Make sure the payload has not already been set. */
- if (!force && bt_ctf_field_is_set_recursive(integer)) {
- /* Payload already set, not an error */
- BT_LOGV("Field's payload is already set: struct-field-addr=%p, "
- "name=\"%s\", force=%d", structure, name, force);
- goto end;
- }
-
- field_type = bt_ctf_field_get_type(integer);
- BT_ASSERT(field_type);
- if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
- /*
- * The user most likely meant for us to populate this field
- * automatically. However, we can only do this if the field
- * is an integer. Return an error.
- */
- BT_LOGW("Invalid parameter: field's type is not an integer field type: "
- "field-addr=%p, ft-addr=%p, ft-id=%s",
- integer, field_type,
- bt_ctf_field_type_id_string((int)
- bt_ctf_field_type_get_type_id(field_type)));
- ret = -1;
- goto end;
- }
-
- if (bt_ctf_field_type_integer_is_signed(field_type)) {
- ret = bt_ctf_field_integer_signed_set_value(integer,
- (int64_t) value);
- } else {
- ret = bt_ctf_field_integer_unsigned_set_value(integer, value);
- }
- ret = !ret ? 1 : ret;
-end:
- bt_ctf_object_put_ref(integer);
- bt_ctf_object_put_ref(field_type);
- return ret;
-}
-
-/*
- * Returns the following codes:
- * 1 if the field was found and set,
- * 0 if nothing was done (field not found, or was already set),
- * <0 if an error was encoutered
- */
-static
-int try_set_structure_field_integer(struct bt_ctf_field *structure, char *name,
- uint64_t value)
-{
- return _set_structure_field_integer(structure, name, value, BT_FALSE);
-}
-
-struct bt_ctf_stream_class *bt_ctf_stream_get_class(
- struct bt_ctf_stream *stream)
-{
- return bt_ctf_object_get_ref(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_ctf_stream_common_get_name(BT_CTF_TO_COMMON(stream));
-}
-
-int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream)
-{
- return bt_ctf_stream_common_get_id(BT_CTF_TO_COMMON(stream));
-}
+++ /dev/null
-/*
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-TRACE"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/attributes-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/clock-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/event.h>
-#include <babeltrace2/ctf-writer/event-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-wrapper-internal.h>
-#include <babeltrace2/ctf-writer/functor-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/stream-internal.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/utils-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/validation-internal.h>
-#include <babeltrace2/ctf-writer/visitor-internal.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/types.h>
-#include <babeltrace2/ctf-writer/values-internal.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_ctf_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_ctf_object_init_shared_with_parent(&trace->base, release_func);
- trace->clock_classes = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_ctf_object_put_ref);
- 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_ctf_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_ctf_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_ctf_object_put_ref(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_ctf_private_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_ctf_value_is_integer(bt_ctf_private_value_as_value(value)) &&
- !bt_ctf_value_is_string(bt_ctf_private_value_as_value(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_ctf_value_type_string(
- bt_ctf_value_get_type(
- bt_ctf_private_value_as_value(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_ctf_private_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_ctf_value_freeze(bt_ctf_private_value_as_value(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_ctf_private_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_ctf_private_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_ctf_object_put_ref(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_ctf_private_value *env_value_integer_obj = NULL;
-
- env_value_integer_obj = bt_ctf_private_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_ctf_object_put_ref(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_ctf_object_get_ref(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;
- }
- }
- }
-
- /*
- * 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_ctf_object_put_ref(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_ctf_object_get_ref(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_ctf_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_CTF_OBJECT_MOVE_REF(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_ctf_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_ctf_object_put_ref(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_ctf_object_put_ref(trace->packet_header_field_type);
- trace->packet_header_field_type = bt_ctf_object_get_ref(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 = bt_ctf_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_ctf_object *obj)
-{
- struct bt_ctf_trace *trace = (void *) obj;
-
- BT_LOGD("Destroying CTF writer trace object: addr=%p, name=\"%s\"",
- trace, bt_ctf_trace_get_name(trace));
- bt_ctf_trace_common_finalize(BT_CTF_TO_COMMON(trace));
- g_free(trace);
-}
-
-BT_HIDDEN
-struct bt_ctf_trace *bt_ctf_trace_create(void)
-{
- struct bt_ctf_trace *trace = NULL;
- int ret;
-
- BT_LOGD_STR("Creating CTF writer trace object.");
- trace = g_new0(struct bt_ctf_trace, 1);
- if (!trace) {
- BT_LOGE_STR("Failed to allocate one CTF writer trace.");
- goto error;
- }
-
- ret = bt_ctf_trace_common_initialize(BT_CTF_TO_COMMON(trace),
- bt_ctf_trace_destroy);
- if (ret) {
- /* bt_ctf_trace_common_initialize() logs errors */
- goto error;
- }
-
- BT_LOGD("Created CTF writer trace object: addr=%p", trace);
- return trace;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(trace);
- return trace;
-}
-
-const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *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_ctf_trace_common_set_uuid(BT_CTF_TO_COMMON(trace), uuid);
-}
-
-int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
- const char *name, const char *value)
-{
- 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_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_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_ctf_trace_common_get_environment_field_name_by_index(
- BT_CTF_TO_COMMON(trace), index);
-}
-
-struct bt_ctf_value *bt_ctf_trace_get_environment_field_value_by_index(
- struct bt_ctf_trace *trace, uint64_t index)
-{
- return bt_ctf_object_get_ref(bt_ctf_trace_common_borrow_environment_field_value_by_index(
- BT_CTF_TO_COMMON(trace), index));
-}
-
-struct bt_ctf_value *bt_ctf_trace_get_environment_field_value_by_name(
- struct bt_ctf_trace *trace, const char *name)
-{
- return bt_ctf_object_get_ref(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_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_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_ctf_object_get_ref(bt_ctf_trace_common_borrow_clock_class_by_index(
- BT_CTF_TO_COMMON(trace), index));
-}
-
-static
-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_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.");
- }
-
- return ret;
-}
-
-int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
- struct bt_ctf_stream_class *stream_class)
-{
- int ret = 0;
- struct bt_ctf_clock_class *expected_clock_class = NULL;
-
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- ret = -1;
- goto end;
- }
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (stream_class->clock) {
- struct bt_ctf_clock_class *stream_clock_class =
- stream_class->clock->clock_class;
-
- /*
- * Make sure this clock was also added to the
- * trace (potentially through its CTF writer
- * owner).
- */
- size_t i;
-
- for (i = 0; i < trace->common.clock_classes->len; i++) {
- if (trace->common.clock_classes->pdata[i] ==
- stream_clock_class) {
- /* Found! */
- break;
- }
- }
-
- if (i == trace->common.clock_classes->len) {
- /* Not found */
- BT_LOGW("Stream class's clock's class is not part of the trace: "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- stream_clock_class,
- bt_ctf_clock_class_get_name(stream_clock_class));
- ret = -1;
- goto end;
- }
-
- if (stream_class->common.clock_class &&
- stream_class->common.clock_class !=
- stream_class->clock->clock_class) {
- /*
- * Stream class already has an expected clock
- * class, but it does not match its clock's
- * class.
- */
- BT_LOGW("Invalid parameter: stream class's clock's "
- "class does not match stream class's "
- "expected clock class: "
- "stream-class-addr=%p, "
- "stream-class-id=%" PRId64 ", "
- "stream-class-name=\"%s\", "
- "expected-clock-class-addr=%p, "
- "expected-clock-class-name=\"%s\"",
- stream_class,
- bt_ctf_stream_class_get_id(stream_class),
- bt_ctf_stream_class_get_name(stream_class),
- 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 = stream_class->clock->clock_class;
- }
- }
-
-
- 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);
-
-end:
- return ret;
-}
-
-int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *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_ctf_object_get_ref(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_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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(
- bt_ctf_trace_common_borrow_clock_class_by_name(BT_CTF_TO_COMMON(trace),
- name));
-}
-
-static
-int append_trace_metadata(struct bt_ctf_trace *trace,
- struct metadata_context *context)
-{
- unsigned char *uuid = trace->common.uuid;
- int ret = 0;
-
- if (trace->common.native_byte_order == BT_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\"",
- trace, bt_ctf_trace_get_name(trace));
- ret = -1;
- goto end;
- }
-
- g_string_append(context->string, "trace {\n");
- g_string_append(context->string, "\tmajor = 1;\n");
- g_string_append(context->string, "\tminor = 8;\n");
- BT_ASSERT(trace->common.native_byte_order == BT_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,
- "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]);
- }
-
- g_string_append_printf(context->string, "\tbyte_order = %s;\n",
- 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 := ");
- context->current_indentation_level++;
- g_string_assign(context->field_name, "");
- BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
- ret = bt_ctf_field_type_serialize_recursive(
- (void *) trace->common.packet_header_field_type,
- context);
- if (ret) {
- goto end;
- }
- context->current_indentation_level--;
- }
-
- g_string_append(context->string, ";\n};\n\n");
-end:
- return ret;
-}
-
-static
-void append_env_metadata(struct bt_ctf_trace *trace,
- struct metadata_context *context)
-{
- int64_t i;
- int64_t env_size;
-
- env_size = bt_ctf_attributes_get_count(trace->common.environment);
- if (env_size <= 0) {
- return;
- }
-
- g_string_append(context->string, "env {\n");
-
- for (i = 0; i < env_size; i++) {
- struct bt_ctf_private_value *env_field_value_obj = NULL;
- const char *entry_name;
-
- entry_name = bt_ctf_attributes_get_field_name(
- trace->common.environment, i);
- env_field_value_obj = bt_ctf_attributes_borrow_field_value(
- trace->common.environment, i);
-
- BT_ASSERT(entry_name);
- BT_ASSERT(env_field_value_obj);
-
- switch (bt_ctf_value_get_type(
- bt_ctf_private_value_as_value(env_field_value_obj))) {
- case BT_CTF_VALUE_TYPE_INTEGER:
- {
- int64_t int_value;
-
- int_value = bt_ctf_value_integer_get(
- bt_ctf_private_value_as_value(
- env_field_value_obj));
- g_string_append_printf(context->string,
- "\t%s = %" PRId64 ";\n", entry_name,
- int_value);
- break;
- }
- case BT_CTF_VALUE_TYPE_STRING:
- {
- const char *str_value;
- char *escaped_str = NULL;
-
- str_value = bt_ctf_value_string_get(
- bt_ctf_private_value_as_value(
- env_field_value_obj));
- escaped_str = g_strescape(str_value, NULL);
- if (!escaped_str) {
- BT_LOGE("Cannot escape string: string=\"%s\"",
- str_value);
- continue;
- }
-
- g_string_append_printf(context->string,
- "\t%s = \"%s\";\n", entry_name, escaped_str);
- free(escaped_str);
- break;
- }
- default:
- continue;
- }
- }
-
- g_string_append(context->string, "};\n\n");
-}
-
-char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
-{
- char *metadata = NULL;
- struct metadata_context *context = NULL;
- int err = 0;
- size_t i;
-
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- goto end;
- }
-
- context = g_new0(struct metadata_context, 1);
- if (!context) {
- BT_LOGE_STR("Failed to allocate one metadata context.");
- goto end;
- }
-
- context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
- context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
- g_string_append(context->string, "/* CTF 1.8 */\n\n");
- if (append_trace_metadata(trace, context)) {
- /* append_trace_metadata() logs errors */
- goto error;
- }
- append_env_metadata(trace, context);
- g_ptr_array_foreach(trace->common.clock_classes,
- (GFunc) bt_ctf_clock_class_serialize, context);
-
- for (i = 0; i < trace->common.stream_classes->len; i++) {
- /* bt_ctf_stream_class_serialize() logs details */
- err = bt_ctf_stream_class_serialize(
- trace->common.stream_classes->pdata[i], context);
- if (err) {
- /* bt_ctf_stream_class_serialize() logs errors */
- goto error;
- }
- }
-
- metadata = context->string->str;
-
-error:
- g_string_free(context->string, err ? TRUE : FALSE);
- g_string_free(context->field_name, TRUE);
- g_free(context);
-
-end:
- return metadata;
-}
-
-enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
- struct bt_ctf_trace *trace)
-{
- return (int) bt_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_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_ctf_object_get_ref(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_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_ctf_trace_common_get_name(BT_CTF_TO_COMMON(trace));
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/ctf-writer/clock-class-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/utils.h>
-#include <babeltrace2/ctf-writer/object.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;
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-pre-internal.h>
-#include <babeltrace2/babeltrace-internal.h>
-#include <babeltrace2/ctf-writer/event-class-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/resolve-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/validation-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctf-writer/values-internal.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_ctf_private_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_ctf_private_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_ctf_private_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_ctf_private_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_ctf_object_get_ref(packet_header_type);
- bt_ctf_object_get_ref(packet_context_type);
- bt_ctf_object_get_ref(event_header_type);
- bt_ctf_object_get_ref(stream_event_ctx_type);
- bt_ctf_object_get_ref(event_context_type);
- bt_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(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_ctf_object_get_ref(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_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(packet_context_type, packet_context_type_copy);
- BT_CTF_OBJECT_MOVE_REF(event_header_type, event_header_type_copy);
- BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(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_ctf_object_get_ref(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_ctf_object_get_ref(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_CTF_OBJECT_MOVE_REF(event_context_type, event_context_type_copy);
- BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_MOVE_REF(output->packet_header_type, packet_header_type);
- BT_CTF_OBJECT_MOVE_REF(output->packet_context_type, packet_context_type);
- BT_CTF_OBJECT_MOVE_REF(output->event_header_type, event_header_type);
- BT_CTF_OBJECT_MOVE_REF(output->stream_event_ctx_type, stream_event_ctx_type);
- BT_CTF_OBJECT_MOVE_REF(output->event_context_type, event_context_type);
- BT_CTF_OBJECT_MOVE_REF(output->event_payload_type, event_payload_type);
- return ret;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_header_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(packet_context_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(event_header_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(stream_event_ctx_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(event_context_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(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_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_MOVE_REF(stream_class->packet_context_field_type,
- output->packet_context_type);
- BT_CTF_OBJECT_MOVE_REF(stream_class->event_header_field_type,
- output->event_header_type);
- BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_MOVE_REF(event_class->context_field_type, output->event_context_type);
- BT_CTF_OBJECT_MOVE_REF(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_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_header_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(output->packet_context_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_header_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(output->stream_event_ctx_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_context_type);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(output->event_payload_type);
-}
+++ /dev/null
-/*
- * 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-VALUES"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <string.h>
-#include <inttypes.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/common-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <babeltrace2/ctf-writer/values-internal.h>
-#include <babeltrace2/compat/glib-internal.h>
-#include <babeltrace2/types.h>
-#include <babeltrace2/ctf-writer/object-internal.h>
-#include <babeltrace2/ctf-writer/values-internal.h>
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/assert-pre-internal.h>
-
-#define BT_CTF_VALUE_FROM_CONCRETE(_concrete) ((struct bt_ctf_value *) (_concrete))
-#define BT_CTF_VALUE_TO_BOOL(_base) ((struct bt_ctf_value_bool *) (_base))
-#define BT_CTF_VALUE_TO_INTEGER(_base) ((struct bt_ctf_value_integer *) (_base))
-#define BT_CTF_VALUE_TO_REAL(_base) ((struct bt_ctf_value_real *) (_base))
-#define BT_CTF_VALUE_TO_STRING(_base) ((struct bt_ctf_value_string *) (_base))
-#define BT_CTF_VALUE_TO_ARRAY(_base) ((struct bt_ctf_value_array *) (_base))
-#define BT_CTF_VALUE_TO_MAP(_base) ((struct bt_ctf_value_map *) (_base))
-
-#define BT_ASSERT_PRE_VALUE_IS_TYPE(_value, _type) \
- BT_ASSERT_PRE(((struct bt_ctf_value *) (_value))->type == (_type), \
- "Value has the wrong type ID: expected-type=%d, " \
- "%![value-]+v", (_type), \
- (_value))
-
-#define BT_ASSERT_PRE_VALUE_HOT(_value, _name) \
- BT_ASSERT_PRE_HOT(((struct bt_ctf_value *) (_value)), (_name), \
- ": %!+v", (_value))
-
-#define BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(_index, _count) \
- BT_ASSERT_PRE((_index) < (_count), \
- "Index is out of bound: " \
- "index=%" PRIu64 ", count=%u", (_index), (_count));
-
-struct bt_ctf_value {
- struct bt_ctf_object base;
- enum bt_ctf_value_type type;
- bt_bool frozen;
-};
-
-static
-void bt_ctf_value_null_instance_release_func(struct bt_ctf_object *obj)
-{
- BT_LOGW("Releasing the null value singleton: addr=%p", obj);
-}
-
-static
-struct bt_ctf_value bt_ctf_value_null_instance = {
- .base = {
- .is_shared = true,
- .ref_count = 1,
- .release_func = bt_ctf_value_null_instance_release_func,
- .spec_release_func = NULL,
- .parent_is_owner_listener_func = NULL,
- .parent = NULL,
- },
- .type = BT_CTF_VALUE_TYPE_NULL,
- .frozen = BT_TRUE,
-};
-
-struct bt_ctf_value *const bt_ctf_value_null = &bt_ctf_value_null_instance;
-struct bt_ctf_private_value *const bt_ctf_private_value_null =
- (void *) &bt_ctf_value_null_instance;
-
-struct bt_ctf_value_bool {
- struct bt_ctf_value base;
- bt_bool value;
-};
-
-struct bt_ctf_value_integer {
- struct bt_ctf_value base;
- int64_t value;
-};
-
-struct bt_ctf_value_real {
- struct bt_ctf_value base;
- double value;
-};
-
-struct bt_ctf_value_string {
- struct bt_ctf_value base;
- GString *gstr;
-};
-
-struct bt_ctf_value_array {
- struct bt_ctf_value base;
- GPtrArray *garray;
-};
-
-struct bt_ctf_value_map {
- struct bt_ctf_value base;
- GHashTable *ght;
-};
-
-static
-void bt_ctf_value_destroy(struct bt_ctf_object *obj);
-
-static
-void bt_ctf_value_string_destroy(struct bt_ctf_value *object)
-{
- g_string_free(BT_CTF_VALUE_TO_STRING(object)->gstr, TRUE);
- BT_CTF_VALUE_TO_STRING(object)->gstr = NULL;
-}
-
-static
-void bt_ctf_value_array_destroy(struct bt_ctf_value *object)
-{
- /*
- * Pointer array's registered value destructor will take care
- * of putting each contained object.
- */
- g_ptr_array_free(BT_CTF_VALUE_TO_ARRAY(object)->garray, TRUE);
- BT_CTF_VALUE_TO_ARRAY(object)->garray = NULL;
-}
-
-static
-void bt_ctf_value_map_destroy(struct bt_ctf_value *object)
-{
- /*
- * Hash table's registered value destructor will take care of
- * putting each contained object. Keys are GQuarks and cannot
- * be destroyed anyway.
- */
- g_hash_table_destroy(BT_CTF_VALUE_TO_MAP(object)->ght);
- BT_CTF_VALUE_TO_MAP(object)->ght = NULL;
-}
-
-static
-void (* const destroy_funcs[])(struct bt_ctf_value *) = {
- [BT_CTF_VALUE_TYPE_NULL] = NULL,
- [BT_CTF_VALUE_TYPE_BOOL] = NULL,
- [BT_CTF_VALUE_TYPE_INTEGER] = NULL,
- [BT_CTF_VALUE_TYPE_REAL] = NULL,
- [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_destroy,
- [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_destroy,
- [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_destroy,
-};
-
-static
-struct bt_ctf_private_value *bt_ctf_value_null_copy(const struct bt_ctf_value *null_obj)
-{
- return (void *) bt_ctf_value_null;
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_bool_copy(const struct bt_ctf_value *bool_obj)
-{
- return bt_ctf_private_value_bool_create_init(
- BT_CTF_VALUE_TO_BOOL(bool_obj)->value);
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_integer_copy(
- const struct bt_ctf_value *integer_obj)
-{
- return bt_ctf_private_value_integer_create_init(
- BT_CTF_VALUE_TO_INTEGER(integer_obj)->value);
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_real_copy(const struct bt_ctf_value *real_obj)
-{
- return bt_ctf_private_value_real_create_init(
- BT_CTF_VALUE_TO_REAL(real_obj)->value);
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_string_copy(const struct bt_ctf_value *string_obj)
-{
- return bt_ctf_private_value_string_create_init(
- BT_CTF_VALUE_TO_STRING(string_obj)->gstr->str);
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_array_copy(const struct bt_ctf_value *array_obj)
-{
- int i;
- int ret;
- struct bt_ctf_private_value *copy_obj;
- struct bt_ctf_value_array *typed_array_obj;
-
- BT_LOGD("Copying array value: addr=%p", array_obj);
- typed_array_obj = BT_CTF_VALUE_TO_ARRAY(array_obj);
- copy_obj = bt_ctf_private_value_array_create();
- if (!copy_obj) {
- BT_LOGE_STR("Cannot create empty array value.");
- goto end;
- }
-
- for (i = 0; i < typed_array_obj->garray->len; ++i) {
- struct bt_ctf_private_value *element_obj_copy = NULL;
- struct bt_ctf_value *element_obj =
- bt_ctf_value_array_borrow_element_by_index(
- array_obj, i);
-
- BT_ASSERT(element_obj);
- BT_LOGD("Copying array value's element: element-addr=%p, "
- "index=%d", element_obj, i);
- ret = bt_ctf_value_copy(&element_obj_copy, element_obj);
- if (ret) {
- BT_LOGE("Cannot copy array value's element: "
- "array-addr=%p, index=%d",
- array_obj, i);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
- goto end;
- }
-
- BT_ASSERT(element_obj_copy);
- ret = bt_ctf_private_value_array_append_element(copy_obj,
- (void *) element_obj_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
- if (ret) {
- BT_LOGE("Cannot append to array value: addr=%p",
- array_obj);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
- goto end;
- }
- }
-
- BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
- array_obj, copy_obj);
-
-end:
- return copy_obj;
-}
-
-static
-struct bt_ctf_private_value *bt_ctf_value_map_copy(const struct bt_ctf_value *map_obj)
-{
- int ret;
- GHashTableIter iter;
- gpointer key, element_obj;
- struct bt_ctf_private_value *copy_obj;
- struct bt_ctf_private_value *element_obj_copy = NULL;
- struct bt_ctf_value_map *typed_map_obj;
-
- BT_LOGD("Copying map value: addr=%p", map_obj);
- typed_map_obj = BT_CTF_VALUE_TO_MAP(map_obj);
- copy_obj = bt_ctf_private_value_map_create();
- if (!copy_obj) {
- goto end;
- }
-
- g_hash_table_iter_init(&iter, typed_map_obj->ght);
-
- while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
- const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
-
- BT_ASSERT(key_str);
- BT_LOGD("Copying map value's element: element-addr=%p, "
- "key=\"%s\"", element_obj, key_str);
- ret = bt_ctf_value_copy(&element_obj_copy, element_obj);
- if (ret) {
- BT_LOGE("Cannot copy map value's element: "
- "map-addr=%p, key=\"%s\"",
- map_obj, key_str);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
- goto end;
- }
-
- BT_ASSERT(element_obj_copy);
- ret = bt_ctf_private_value_map_insert_entry(copy_obj, key_str,
- (void *) element_obj_copy);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
- if (ret) {
- BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
- map_obj, key_str);
- BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_obj);
- goto end;
- }
- }
-
- BT_LOGD("Copied map value: addr=%p", map_obj);
-
-end:
- return copy_obj;
-}
-
-static
-struct bt_ctf_private_value *(* const copy_funcs[])(const struct bt_ctf_value *) = {
- [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_copy,
- [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_bool_copy,
- [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_integer_copy,
- [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_real_copy,
- [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_copy,
- [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_copy,
- [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_copy,
-};
-
-static
-bt_bool bt_ctf_value_null_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- /*
- * Always BT_TRUE since bt_ctf_value_compare() already checks if both
- * object_a and object_b have the same type, and in the case of
- * null value objects, they're always the same if it is so.
- */
- return BT_TRUE;
-}
-
-static
-bt_bool bt_ctf_value_bool_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- if (BT_CTF_VALUE_TO_BOOL(object_a)->value !=
- BT_CTF_VALUE_TO_BOOL(object_b)->value) {
- BT_LOGV("Boolean value objects are different: "
- "bool-a-val=%d, bool-b-val=%d",
- BT_CTF_VALUE_TO_BOOL(object_a)->value,
- BT_CTF_VALUE_TO_BOOL(object_b)->value);
- return BT_FALSE;
- }
-
- return BT_TRUE;
-}
-
-static
-bt_bool bt_ctf_value_integer_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- if (BT_CTF_VALUE_TO_INTEGER(object_a)->value !=
- BT_CTF_VALUE_TO_INTEGER(object_b)->value) {
- BT_LOGV("Integer value objects are different: "
- "int-a-val=%" PRId64 ", int-b-val=%" PRId64,
- BT_CTF_VALUE_TO_INTEGER(object_a)->value,
- BT_CTF_VALUE_TO_INTEGER(object_b)->value);
- return BT_FALSE;
- }
-
- return BT_TRUE;
-}
-
-static
-bt_bool bt_ctf_value_real_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- if (BT_CTF_VALUE_TO_REAL(object_a)->value !=
- BT_CTF_VALUE_TO_REAL(object_b)->value) {
- BT_LOGV("Real number value objects are different: "
- "real-a-val=%f, real-b-val=%f",
- BT_CTF_VALUE_TO_REAL(object_a)->value,
- BT_CTF_VALUE_TO_REAL(object_b)->value);
- return BT_FALSE;
- }
-
- return BT_TRUE;
-}
-
-static
-bt_bool bt_ctf_value_string_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- if (strcmp(BT_CTF_VALUE_TO_STRING(object_a)->gstr->str,
- BT_CTF_VALUE_TO_STRING(object_b)->gstr->str) != 0) {
- BT_LOGV("String value objects are different: "
- "string-a-val=\"%s\", string-b-val=\"%s\"",
- BT_CTF_VALUE_TO_STRING(object_a)->gstr->str,
- BT_CTF_VALUE_TO_STRING(object_b)->gstr->str);
- return BT_FALSE;
- }
-
- return BT_TRUE;
-}
-
-static
-bt_bool bt_ctf_value_array_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- int i;
- bt_bool ret = BT_TRUE;
- const struct bt_ctf_value_array *array_obj_a =
- BT_CTF_VALUE_TO_ARRAY(object_a);
-
- if (bt_ctf_value_array_get_size(object_a) !=
- bt_ctf_value_array_get_size(object_b)) {
- BT_LOGV("Array values are different: size mismatch "
- "value-a-addr=%p, value-b-addr=%p, "
- "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
- object_a, object_b,
- bt_ctf_value_array_get_size(object_a),
- bt_ctf_value_array_get_size(object_b));
- ret = BT_FALSE;
- goto end;
- }
-
- for (i = 0; i < array_obj_a->garray->len; ++i) {
- struct bt_ctf_value *element_obj_a;
- struct bt_ctf_value *element_obj_b;
-
- element_obj_a = bt_ctf_value_array_borrow_element_by_index(
- object_a, i);
- element_obj_b = bt_ctf_value_array_borrow_element_by_index(
- object_b, i);
-
- if (!bt_ctf_value_compare(element_obj_a, element_obj_b)) {
- BT_LOGV("Array values's elements are different: "
- "value-a-addr=%p, value-b-addr=%p, index=%d",
- element_obj_a, element_obj_b, i);
- ret = BT_FALSE;
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-static
-bt_bool bt_ctf_value_map_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- bt_bool ret = BT_TRUE;
- GHashTableIter iter;
- gpointer key, element_obj_a;
- const struct bt_ctf_value_map *map_obj_a = BT_CTF_VALUE_TO_MAP(object_a);
-
- if (bt_ctf_value_map_get_size(object_a) !=
- bt_ctf_value_map_get_size(object_b)) {
- BT_LOGV("Map values are different: size mismatch "
- "value-a-addr=%p, value-b-addr=%p, "
- "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
- object_a, object_b,
- bt_ctf_value_map_get_size(object_a),
- bt_ctf_value_map_get_size(object_b));
- ret = BT_FALSE;
- goto end;
- }
-
- g_hash_table_iter_init(&iter, map_obj_a->ght);
-
- while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
- struct bt_ctf_value *element_obj_b;
- const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
-
- element_obj_b = bt_ctf_value_map_borrow_entry_value(object_b,
- key_str);
-
- if (!bt_ctf_value_compare(element_obj_a, element_obj_b)) {
- BT_LOGV("Map values's elements are different: "
- "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
- element_obj_a, element_obj_b, key_str);
- ret = BT_FALSE;
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-static
-bt_bool (* const compare_funcs[])(const struct bt_ctf_value *,
- const struct bt_ctf_value *) = {
- [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_compare,
- [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_bool_compare,
- [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_integer_compare,
- [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_real_compare,
- [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_string_compare,
- [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_compare,
- [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_compare,
-};
-
-static
-void bt_ctf_value_null_freeze(struct bt_ctf_value *object)
-{
-}
-
-static
-void bt_ctf_value_generic_freeze(struct bt_ctf_value *object)
-{
- object->frozen = BT_TRUE;
-}
-
-static
-void bt_ctf_value_array_freeze(struct bt_ctf_value *object)
-{
- int i;
- struct bt_ctf_value_array *typed_array_obj =
- BT_CTF_VALUE_TO_ARRAY(object);
-
- for (i = 0; i < typed_array_obj->garray->len; ++i) {
- bt_ctf_value_freeze(g_ptr_array_index(typed_array_obj->garray, i));
- }
-
- bt_ctf_value_generic_freeze(object);
-}
-
-static
-void bt_ctf_value_map_freeze(struct bt_ctf_value *object)
-{
- GHashTableIter iter;
- gpointer key, element_obj;
- const struct bt_ctf_value_map *map_obj = BT_CTF_VALUE_TO_MAP(object);
-
- g_hash_table_iter_init(&iter, map_obj->ght);
-
- while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
- bt_ctf_value_freeze(element_obj);
- }
-
- bt_ctf_value_generic_freeze(object);
-}
-
-static
-void (* const freeze_funcs[])(struct bt_ctf_value *) = {
- [BT_CTF_VALUE_TYPE_NULL] = bt_ctf_value_null_freeze,
- [BT_CTF_VALUE_TYPE_BOOL] = bt_ctf_value_generic_freeze,
- [BT_CTF_VALUE_TYPE_INTEGER] = bt_ctf_value_generic_freeze,
- [BT_CTF_VALUE_TYPE_REAL] = bt_ctf_value_generic_freeze,
- [BT_CTF_VALUE_TYPE_STRING] = bt_ctf_value_generic_freeze,
- [BT_CTF_VALUE_TYPE_ARRAY] = bt_ctf_value_array_freeze,
- [BT_CTF_VALUE_TYPE_MAP] = bt_ctf_value_map_freeze,
-};
-
-static
-void bt_ctf_value_destroy(struct bt_ctf_object *obj)
-{
- struct bt_ctf_value *value;
-
- value = container_of(obj, struct bt_ctf_value, base);
- BT_LOGD("Destroying value: addr=%p", value);
-
- if (bt_ctf_value_is_null(value)) {
- BT_LOGD_STR("Not destroying the null value singleton.");
- return;
- }
-
- if (destroy_funcs[value->type]) {
- destroy_funcs[value->type](value);
- }
-
- g_free(value);
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status _bt_ctf_value_freeze(struct bt_ctf_value *object)
-{
- enum bt_ctf_value_status ret = BT_CTF_VALUE_STATUS_OK;
-
- BT_ASSERT(object);
-
- if (object->frozen) {
- goto end;
- }
-
- BT_LOGD("Freezing value: addr=%p", object);
- freeze_funcs[object->type](object);
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_type bt_ctf_value_get_type(const struct bt_ctf_value *object)
-{
- BT_ASSERT_PRE_NON_NULL(object, "Value object");
- return object->type;
-}
-
-static
-struct bt_ctf_value bt_ctf_value_create_base(enum bt_ctf_value_type type)
-{
- struct bt_ctf_value value;
-
- value.type = type;
- value.frozen = BT_FALSE;
- bt_ctf_object_init_shared(&value.base, bt_ctf_value_destroy);
- return value;
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_bool_create_init(bt_bool val)
-{
- struct bt_ctf_value_bool *bool_obj;
-
- BT_LOGD("Creating boolean value object: val=%d", val);
- bool_obj = g_new0(struct bt_ctf_value_bool, 1);
- if (!bool_obj) {
- BT_LOGE_STR("Failed to allocate one boolean value object.");
- goto end;
- }
-
- bool_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_BOOL);
- bool_obj->value = val;
- BT_LOGD("Created boolean value object: addr=%p", bool_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(bool_obj);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_bool_create(void)
-{
- return bt_ctf_private_value_bool_create_init(BT_FALSE);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_integer_create_init(int64_t val)
-{
- struct bt_ctf_value_integer *integer_obj;
-
- BT_LOGD("Creating integer value object: val=%" PRId64, val);
- integer_obj = g_new0(struct bt_ctf_value_integer, 1);
- if (!integer_obj) {
- BT_LOGE_STR("Failed to allocate one integer value object.");
- goto end;
- }
-
- integer_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_INTEGER);
- integer_obj->value = val;
- BT_LOGD("Created integer value object: addr=%p",
- integer_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(integer_obj);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_integer_create(void)
-{
- return bt_ctf_private_value_integer_create_init(0);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_real_create_init(double val)
-{
- struct bt_ctf_value_real *real_obj;
-
- BT_LOGD("Creating real number value object: val=%f", val);
- real_obj = g_new0(struct bt_ctf_value_real, 1);
- if (!real_obj) {
- BT_LOGE_STR("Failed to allocate one real number value object.");
- goto end;
- }
-
- real_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_REAL);
- real_obj->value = val;
- BT_LOGD("Created real number value object: addr=%p",
- real_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(real_obj);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_real_create(void)
-{
- return bt_ctf_private_value_real_create_init(0.);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_string_create_init(const char *val)
-{
- struct bt_ctf_value_string *string_obj = NULL;
-
- if (!val) {
- BT_LOGW_STR("Invalid parameter: value is NULL.");
- goto end;
- }
-
- BT_LOGD("Creating string value object: val-len=%zu", strlen(val));
- string_obj = g_new0(struct bt_ctf_value_string, 1);
- if (!string_obj) {
- BT_LOGE_STR("Failed to allocate one string object.");
- goto end;
- }
-
- string_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_STRING);
- string_obj->gstr = g_string_new(val);
- if (!string_obj->gstr) {
- BT_LOGE_STR("Failed to allocate a GString.");
- g_free(string_obj);
- string_obj = NULL;
- goto end;
- }
-
- BT_LOGD("Created string value object: addr=%p",
- string_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(string_obj);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_string_create(void)
-{
- return bt_ctf_private_value_string_create_init("");
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_array_create(void)
-{
- struct bt_ctf_value_array *array_obj;
-
- BT_LOGD_STR("Creating empty array value object.");
- array_obj = g_new0(struct bt_ctf_value_array, 1);
- if (!array_obj) {
- BT_LOGE_STR("Failed to allocate one array object.");
- goto end;
- }
-
- array_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_ARRAY);
- array_obj->garray = bt_g_ptr_array_new_full(0,
- (GDestroyNotify) bt_ctf_object_put_ref);
- if (!array_obj->garray) {
- BT_LOGE_STR("Failed to allocate a GPtrArray.");
- g_free(array_obj);
- array_obj = NULL;
- goto end;
- }
-
- BT_LOGD("Created array value object: addr=%p",
- array_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(array_obj);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_map_create(void)
-{
- struct bt_ctf_value_map *map_obj;
-
- BT_LOGD_STR("Creating empty map value object.");
- map_obj = g_new0(struct bt_ctf_value_map, 1);
- if (!map_obj) {
- BT_LOGE_STR("Failed to allocate one map object.");
- goto end;
- }
-
- map_obj->base = bt_ctf_value_create_base(BT_CTF_VALUE_TYPE_MAP);
- map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) bt_ctf_object_put_ref);
- if (!map_obj->ght) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
- g_free(map_obj);
- map_obj = NULL;
- goto end;
- }
-
- BT_LOGD("Created map value object: addr=%p",
- map_obj);
-
-end:
- return (void *) BT_CTF_VALUE_FROM_CONCRETE(map_obj);
-}
-
-BT_HIDDEN
-bt_bool bt_ctf_value_bool_get(const struct bt_ctf_value *bool_obj)
-{
- BT_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_CTF_VALUE_TYPE_BOOL);
- return BT_CTF_VALUE_TO_BOOL(bool_obj)->value;
-}
-
-BT_HIDDEN
-void bt_ctf_private_value_bool_set(struct bt_ctf_private_value *bool_obj, bt_bool val)
-{
- BT_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_CTF_VALUE_TYPE_BOOL);
- BT_ASSERT_PRE_VALUE_HOT(bool_obj, "Value object");
- BT_CTF_VALUE_TO_BOOL(bool_obj)->value = val;
- BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
- bool_obj, val);
-}
-
-BT_HIDDEN
-int64_t bt_ctf_value_integer_get(const struct bt_ctf_value *integer_obj)
-{
- BT_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_CTF_VALUE_TYPE_INTEGER);
- return BT_CTF_VALUE_TO_INTEGER(integer_obj)->value;
-}
-
-BT_HIDDEN
-void bt_ctf_private_value_integer_set(struct bt_ctf_private_value *integer_obj,
- int64_t val)
-{
- BT_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_CTF_VALUE_TYPE_INTEGER);
- BT_ASSERT_PRE_VALUE_HOT(integer_obj, "Value object");
- BT_CTF_VALUE_TO_INTEGER(integer_obj)->value = val;
- BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
- integer_obj, val);
-}
-
-BT_HIDDEN
-double bt_ctf_value_real_get(const struct bt_ctf_value *real_obj)
-{
- BT_ASSERT_PRE_NON_NULL(real_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_CTF_VALUE_TYPE_REAL);
- return BT_CTF_VALUE_TO_REAL(real_obj)->value;
-}
-
-BT_HIDDEN
-void bt_ctf_private_value_real_set(struct bt_ctf_private_value *real_obj, double val)
-{
- BT_ASSERT_PRE_NON_NULL(real_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_CTF_VALUE_TYPE_REAL);
- BT_ASSERT_PRE_VALUE_HOT(real_obj, "Value object");
- BT_CTF_VALUE_TO_REAL(real_obj)->value = val;
- BT_LOGV("Set real number value's raw value: value-addr=%p, value=%f",
- real_obj, val);
-}
-
-BT_HIDDEN
-const char *bt_ctf_value_string_get(const struct bt_ctf_value *string_obj)
-{
- BT_ASSERT_PRE_NON_NULL(string_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_CTF_VALUE_TYPE_STRING);
- return BT_CTF_VALUE_TO_STRING(string_obj)->gstr->str;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_string_set(
- struct bt_ctf_private_value *string_obj, const char *val)
-{
- BT_ASSERT_PRE_NON_NULL(string_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_CTF_VALUE_TYPE_STRING);
- BT_ASSERT_PRE_VALUE_HOT(string_obj, "Value object");
- g_string_assign(BT_CTF_VALUE_TO_STRING(string_obj)->gstr, val);
- BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
- string_obj, val);
- return BT_CTF_VALUE_STATUS_OK;
-}
-
-BT_HIDDEN
-uint64_t bt_ctf_value_array_get_size(const struct bt_ctf_value *array_obj)
-{
- BT_ASSERT_PRE_NON_NULL(array_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
- return (uint64_t) BT_CTF_VALUE_TO_ARRAY(array_obj)->garray->len;
-}
-
-BT_HIDDEN
-struct bt_ctf_value *bt_ctf_value_array_borrow_element_by_index(
- const struct bt_ctf_value *array_obj,
- uint64_t index)
-{
- struct bt_ctf_value_array *typed_array_obj =
- BT_CTF_VALUE_TO_ARRAY(array_obj);
-
- BT_ASSERT_PRE_NON_NULL(array_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
- BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
- typed_array_obj->garray->len);
- return g_ptr_array_index(typed_array_obj->garray, index);
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_array_borrow_element_by_index(
- const struct bt_ctf_private_value *array_obj,
- uint64_t index)
-{
- return (void *) bt_ctf_value_array_borrow_element_by_index(
- (void *) array_obj, index);
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_element(
- struct bt_ctf_private_value *array_obj,
- struct bt_ctf_value *element_obj)
-{
- struct bt_ctf_value_array *typed_array_obj =
- BT_CTF_VALUE_TO_ARRAY(array_obj);
-
- BT_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
- BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
- BT_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
- g_ptr_array_add(typed_array_obj->garray, element_obj);
- bt_ctf_object_get_ref(element_obj);
- BT_LOGV("Appended element to array value: array-value-addr=%p, "
- "element-value-addr=%p, new-size=%u",
- array_obj, element_obj, typed_array_obj->garray->len);
- return BT_CTF_VALUE_STATUS_OK;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_bool_element(
- struct bt_ctf_private_value *array_obj, bt_bool val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *bool_obj = NULL;
-
- bool_obj = bt_ctf_private_value_bool_create_init(val);
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) bool_obj);
- bt_ctf_object_put_ref(bool_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_integer_element(
- struct bt_ctf_private_value *array_obj, int64_t val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *integer_obj = NULL;
-
- integer_obj = bt_ctf_private_value_integer_create_init(val);
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) integer_obj);
- bt_ctf_object_put_ref(integer_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_real_element(
- struct bt_ctf_private_value *array_obj, double val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *real_obj = NULL;
-
- real_obj = bt_ctf_private_value_real_create_init(val);
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) real_obj);
- bt_ctf_object_put_ref(real_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_string_element(
- struct bt_ctf_private_value *array_obj, const char *val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *string_obj = NULL;
-
- string_obj = bt_ctf_private_value_string_create_init(val);
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) string_obj);
- bt_ctf_object_put_ref(string_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_empty_array_element(
- struct bt_ctf_private_value *array_obj)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *empty_array_obj = NULL;
-
- empty_array_obj = bt_ctf_private_value_array_create();
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) empty_array_obj);
- bt_ctf_object_put_ref(empty_array_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_append_empty_map_element(
- struct bt_ctf_private_value *array_obj)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *map_obj = NULL;
-
- map_obj = bt_ctf_private_value_map_create();
- ret = bt_ctf_private_value_array_append_element(array_obj,
- (void *) map_obj);
- bt_ctf_object_put_ref(map_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_array_set_element_by_index(
- struct bt_ctf_private_value *array_obj, uint64_t index,
- struct bt_ctf_value *element_obj)
-{
- struct bt_ctf_value_array *typed_array_obj =
- BT_CTF_VALUE_TO_ARRAY(array_obj);
-
- BT_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
- BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_CTF_VALUE_TYPE_ARRAY);
- BT_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
- BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
- typed_array_obj->garray->len);
- bt_ctf_object_put_ref(g_ptr_array_index(typed_array_obj->garray, index));
- g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
- bt_ctf_object_get_ref(element_obj);
- BT_LOGV("Set array value's element: array-value-addr=%p, "
- "index=%" PRIu64 ", element-value-addr=%p",
- array_obj, index, element_obj);
- return BT_CTF_VALUE_STATUS_OK;
-}
-
-BT_HIDDEN
-uint64_t bt_ctf_value_map_get_size(const struct bt_ctf_value *map_obj)
-{
- BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
- return (uint64_t) g_hash_table_size(BT_CTF_VALUE_TO_MAP(map_obj)->ght);
-}
-
-BT_HIDDEN
-struct bt_ctf_value *bt_ctf_value_map_borrow_entry_value(const struct bt_ctf_value *map_obj,
- const char *key)
-{
- BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
- BT_ASSERT_PRE_NON_NULL(key, "Key");
- BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
- return g_hash_table_lookup(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
- GUINT_TO_POINTER(g_quark_from_string(key)));
-}
-
-BT_HIDDEN
-struct bt_ctf_private_value *bt_ctf_private_value_map_borrow_entry_value(
- const struct bt_ctf_private_value *map_obj, const char *key)
-{
- return (void *) bt_ctf_value_map_borrow_entry_value((void *) map_obj, key);
-}
-
-BT_HIDDEN
-bt_bool bt_ctf_value_map_has_entry(const struct bt_ctf_value *map_obj, const char *key)
-{
- BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
- BT_ASSERT_PRE_NON_NULL(key, "Key");
- BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
- return bt_g_hash_table_contains(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
- GUINT_TO_POINTER(g_quark_from_string(key)));
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_entry(
- struct bt_ctf_private_value *map_obj,
- const char *key, struct bt_ctf_value *element_obj)
-{
- BT_ASSERT_PRE_NON_NULL(map_obj, "Map value object");
- BT_ASSERT_PRE_NON_NULL(key, "Key");
- BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
- BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
- BT_ASSERT_PRE_VALUE_HOT(map_obj, "Map value object");
- g_hash_table_insert(BT_CTF_VALUE_TO_MAP(map_obj)->ght,
- GUINT_TO_POINTER(g_quark_from_string(key)), element_obj);
- bt_ctf_object_get_ref(element_obj);
- BT_LOGV("Inserted value into map value: map-value-addr=%p, "
- "key=\"%s\", element-value-addr=%p",
- map_obj, key, element_obj);
- return BT_CTF_VALUE_STATUS_OK;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_bool_entry(
- struct bt_ctf_private_value *map_obj, const char *key, bt_bool val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *bool_obj = NULL;
-
- bool_obj = bt_ctf_private_value_bool_create_init(val);
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) bool_obj);
- bt_ctf_object_put_ref(bool_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_integer_entry(
- struct bt_ctf_private_value *map_obj, const char *key, int64_t val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *integer_obj = NULL;
-
- integer_obj = bt_ctf_private_value_integer_create_init(val);
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) integer_obj);
- bt_ctf_object_put_ref(integer_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_real_entry(
- struct bt_ctf_private_value *map_obj, const char *key, double val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *real_obj = NULL;
-
- real_obj = bt_ctf_private_value_real_create_init(val);
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) real_obj);
- bt_ctf_object_put_ref(real_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_string_entry(
- struct bt_ctf_private_value *map_obj, const char *key,
- const char *val)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *string_obj = NULL;
-
- string_obj = bt_ctf_private_value_string_create_init(val);
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) string_obj);
- bt_ctf_object_put_ref(string_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_empty_array_entry(
- struct bt_ctf_private_value *map_obj, const char *key)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *array_obj = NULL;
-
- array_obj = bt_ctf_private_value_array_create();
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) array_obj);
- bt_ctf_object_put_ref(array_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_insert_empty_map_entry(
- struct bt_ctf_private_value *map_obj, const char *key)
-{
- enum bt_ctf_value_status ret;
- struct bt_ctf_private_value *empty_map_obj = NULL;
-
- empty_map_obj = bt_ctf_private_value_map_create();
- ret = bt_ctf_private_value_map_insert_entry(map_obj, key,
- (void *) empty_map_obj);
- bt_ctf_object_put_ref(empty_map_obj);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_value_map_foreach_entry(const struct bt_ctf_value *map_obj,
- bt_ctf_value_map_foreach_entry_cb cb, void *data)
-{
- enum bt_ctf_value_status ret = BT_CTF_VALUE_STATUS_OK;
- gpointer key, element_obj;
- GHashTableIter iter;
- struct bt_ctf_value_map *typed_map_obj = BT_CTF_VALUE_TO_MAP(map_obj);
-
- BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
- BT_ASSERT_PRE_NON_NULL(cb, "Callback");
- BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_CTF_VALUE_TYPE_MAP);
- g_hash_table_iter_init(&iter, typed_map_obj->ght);
-
- while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
- const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
-
- if (!cb(key_str, element_obj, data)) {
- BT_LOGV("User canceled the loop: key=\"%s\", "
- "value-addr=%p, data=%p",
- key_str, element_obj, data);
- ret = BT_CTF_VALUE_STATUS_CANCELED;
- break;
- }
- }
-
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_private_value_map_foreach_entry(
- const struct bt_ctf_private_value *map_obj,
- bt_ctf_private_value_map_foreach_entry_cb cb, void *data)
-{
- return bt_ctf_value_map_foreach_entry((void *) map_obj,
- (bt_ctf_value_map_foreach_entry_cb) cb, data);
-}
-
-struct extend_map_element_data {
- struct bt_ctf_private_value *extended_obj;
- enum bt_ctf_value_status status;
-};
-
-static
-bt_bool extend_map_element(const char *key,
- struct bt_ctf_value *extension_obj_elem, void *data)
-{
- bt_bool ret = BT_TRUE;
- struct extend_map_element_data *extend_data = data;
- struct bt_ctf_private_value *extension_obj_elem_copy = NULL;
-
- /* Copy object which is to replace the current one */
- extend_data->status = bt_ctf_value_copy(&extension_obj_elem_copy,
- extension_obj_elem);
- if (extend_data->status) {
- BT_LOGE("Cannot copy map element: addr=%p",
- extension_obj_elem);
- goto error;
- }
-
- BT_ASSERT(extension_obj_elem_copy);
-
- /* Replace in extended object */
- extend_data->status = bt_ctf_private_value_map_insert_entry(
- extend_data->extended_obj, key,
- (void *) extension_obj_elem_copy);
- if (extend_data->status) {
- BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
- "extended-value-addr=%p, element-value-addr=%p",
- key, extend_data->extended_obj,
- extension_obj_elem_copy);
- goto error;
- }
-
- goto end;
-
-error:
- BT_ASSERT(extend_data->status != BT_CTF_VALUE_STATUS_OK);
- ret = BT_FALSE;
-
-end:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
- return ret;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_value_map_extend(
- struct bt_ctf_private_value **extended_map_obj,
- const struct bt_ctf_value *base_map_obj,
- const struct bt_ctf_value *extension_obj)
-{
- struct extend_map_element_data extend_data = {
- .extended_obj = NULL,
- .status = BT_CTF_VALUE_STATUS_OK,
- };
-
- BT_ASSERT_PRE_NON_NULL(base_map_obj, "Base value object");
- BT_ASSERT_PRE_NON_NULL(extension_obj, "Extension value object");
- BT_ASSERT_PRE_NON_NULL(extended_map_obj,
- "Extended value object (output)");
- BT_ASSERT_PRE_VALUE_IS_TYPE(base_map_obj, BT_CTF_VALUE_TYPE_MAP);
- BT_ASSERT_PRE_VALUE_IS_TYPE(extension_obj, BT_CTF_VALUE_TYPE_MAP);
- BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
- base_map_obj, extension_obj);
- *extended_map_obj = NULL;
-
- /* Create copy of base map object to start with */
- extend_data.status = bt_ctf_value_copy(extended_map_obj, base_map_obj);
- if (extend_data.status) {
- BT_LOGE("Cannot copy base value: base-value-addr=%p",
- base_map_obj);
- goto error;
- }
-
- BT_ASSERT(extended_map_obj);
-
- /*
- * For each key in the extension map object, replace this key
- * in the copied map object.
- */
- extend_data.extended_obj = *extended_map_obj;
-
- if (bt_ctf_value_map_foreach_entry(extension_obj, extend_map_element,
- &extend_data)) {
- BT_LOGE("Cannot iterate on the extension object's elements: "
- "extension-value-addr=%p", extension_obj);
- goto error;
- }
-
- if (extend_data.status) {
- BT_LOGE("Failed to successfully iterate on the extension object's elements: "
- "extension-value-addr=%p", extension_obj);
- goto error;
- }
-
- BT_LOGD("Extended map value: extended-value-addr=%p",
- *extended_map_obj);
- goto end;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(*extended_map_obj);
- *extended_map_obj = NULL;
-
-end:
- return extend_data.status;
-}
-
-BT_HIDDEN
-enum bt_ctf_value_status bt_ctf_value_copy(struct bt_ctf_private_value **copy_obj,
- const struct bt_ctf_value *object)
-{
- enum bt_ctf_value_status status = BT_CTF_VALUE_STATUS_OK;
-
- BT_ASSERT_PRE_NON_NULL(object, "Value object");
- BT_ASSERT_PRE_NON_NULL(copy_obj, "Value object copy (output)");
- BT_LOGD("Copying value object: addr=%p", object);
- *copy_obj = copy_funcs[object->type](object);
- if (*copy_obj) {
- BT_LOGD("Copied value object: copy-value-addr=%p",
- copy_obj);
- } else {
- status = BT_CTF_VALUE_STATUS_NOMEM;
- *copy_obj = NULL;
- BT_LOGE_STR("Failed to copy value object.");
- }
-
- return status;
-}
-
-BT_HIDDEN
-bt_bool bt_ctf_value_compare(const struct bt_ctf_value *object_a,
- const struct bt_ctf_value *object_b)
-{
- bt_bool ret = BT_FALSE;
-
- BT_ASSERT_PRE_NON_NULL(object_a, "Value object A");
- BT_ASSERT_PRE_NON_NULL(object_b, "Value object B");
-
- if (object_a->type != object_b->type) {
- BT_LOGV("Values are different: type mismatch: "
- "value-a-addr=%p, value-b-addr=%p, "
- "value-a-type=%d, value-b-type=%d",
- object_a, object_b, object_a->type, object_b->type);
- goto end;
- }
-
- ret = compare_funcs[object_a->type](object_a, object_b);
-
-end:
- return ret;
-}
+++ /dev/null
-/*
- * 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 <babeltrace2/ctf-writer/visitor-internal.h>
-#include <babeltrace2/ctf-writer/object.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_CTF_OBJECT_PUT_REF_AND_RESET(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;
-}
+++ /dev/null
-/*
- * writer.c
- *
- * Babeltrace CTF Writer
- *
- * 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"
-#include <babeltrace2/lib-logging-internal.h>
-
-#include <babeltrace2/assert-internal.h>
-#include <babeltrace2/compat/uuid-internal.h>
-#include <babeltrace2/compiler-internal.h>
-#include <babeltrace2/ctf-writer/clock-internal.h>
-#include <babeltrace2/ctf-writer/field-types-internal.h>
-#include <babeltrace2/ctf-writer/fields-internal.h>
-#include <babeltrace2/ctf-writer/functor-internal.h>
-#include <babeltrace2/ctf-writer/stream-class-internal.h>
-#include <babeltrace2/ctf-writer/stream-internal.h>
-#include <babeltrace2/ctf-writer/trace-internal.h>
-#include <babeltrace2/ctf-writer/writer-internal.h>
-#include <babeltrace2/endian-internal.h>
-#include <babeltrace2/ctf-writer/object.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static
-void bt_ctf_writer_destroy(struct bt_ctf_object *obj);
-
-static
-int init_trace_packet_header(struct bt_ctf_trace *trace)
-{
- int ret = 0;
- struct bt_ctf_field_type *_uint32_t =
- get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
- struct bt_ctf_field_type *_uint8_t =
- get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
- struct bt_ctf_field_type *trace_packet_header_type =
- bt_ctf_field_type_structure_create();
- struct bt_ctf_field_type *uuid_array_type =
- bt_ctf_field_type_array_create(_uint8_t, 16);
-
- if (!trace_packet_header_type || !uuid_array_type) {
- ret = -1;
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
- _uint32_t, "magic");
- if (ret) {
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
- uuid_array_type, "uuid");
- if (ret) {
- goto end;
- }
-
- ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
- _uint32_t, "stream_id");
- if (ret) {
- goto end;
- }
-
- ret = bt_ctf_trace_set_packet_header_field_type(trace,
- trace_packet_header_type);
- if (ret) {
- goto end;
- }
-end:
- bt_ctf_object_put_ref(uuid_array_type);
- bt_ctf_object_put_ref(_uint32_t);
- bt_ctf_object_put_ref(_uint8_t);
- bt_ctf_object_put_ref(trace_packet_header_type);
- return ret;
-}
-
-struct bt_ctf_writer *bt_ctf_writer_create(const char *path)
-{
- int ret;
- struct bt_ctf_writer *writer = NULL;
- unsigned char uuid[16];
- char *metadata_path = NULL;
-
- if (!path) {
- goto error;
- }
-
- writer = g_new0(struct bt_ctf_writer, 1);
- if (!writer) {
- goto error;
- }
-
- metadata_path = g_build_filename(path, "metadata", NULL);
-
- bt_ctf_object_init_shared(&writer->base, bt_ctf_writer_destroy);
- writer->path = g_string_new(path);
- if (!writer->path) {
- goto error_destroy;
- }
-
- writer->trace = bt_ctf_trace_create();
- if (!writer->trace) {
- goto error_destroy;
- }
-
- ret = init_trace_packet_header(writer->trace);
- if (ret) {
- goto error_destroy;
- }
-
- /* Generate a UUID for this writer's trace */
- ret = bt_uuid_generate(uuid);
- if (ret) {
- BT_LOGE_STR("Cannot generate UUID for CTF writer's trace.");
- goto error_destroy;
- }
-
- ret = bt_ctf_trace_set_uuid(writer->trace, uuid);
- if (ret) {
- goto error_destroy;
- }
-
- bt_ctf_object_set_parent(&writer->trace->common.base, &writer->base);
- bt_ctf_object_put_ref(writer->trace);
-
- /* Default to little-endian */
- ret = bt_ctf_writer_set_byte_order(writer, BT_CTF_BYTE_ORDER_NATIVE);
- BT_ASSERT(ret == 0);
-
- /* Create trace directory if necessary and open a metadata file */
- if (g_mkdir_with_parents(path, S_IRWXU | S_IRWXG)) {
- perror("g_mkdir_with_parents");
- goto error_destroy;
- }
-
- writer->metadata_fd = open(metadata_path,
- O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (writer->metadata_fd < 0) {
- perror("open");
- goto error_destroy;
- }
-
- g_free(metadata_path);
- return writer;
-
-error_destroy:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(writer);
-error:
- g_free(metadata_path);
- return writer;
-}
-
-void bt_ctf_writer_destroy(struct bt_ctf_object *obj)
-{
- struct bt_ctf_writer *writer;
-
- writer = container_of(obj, struct bt_ctf_writer, base);
- bt_ctf_writer_flush_metadata(writer);
- if (writer->path) {
- g_string_free(writer->path, TRUE);
- }
-
- if (writer->metadata_fd > 0) {
- if (close(writer->metadata_fd)) {
- perror("close");
- }
- }
-
- bt_ctf_object_try_spec_release(&writer->trace->common.base);
- g_free(writer);
-}
-
-struct bt_ctf_trace *bt_ctf_writer_get_trace(struct bt_ctf_writer *writer)
-{
- struct bt_ctf_trace *trace = NULL;
-
- if (!writer) {
- goto end;
- }
-
- trace = writer->trace;
- bt_ctf_object_get_ref(trace);
-end:
- return trace;
-}
-
-struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
- struct bt_ctf_stream_class *stream_class)
-{
- struct bt_ctf_stream *stream = NULL;
- int stream_class_count;
- bt_bool stream_class_found = BT_FALSE;
- int i;
-
- if (!writer || !stream_class) {
- goto error;
- }
-
- /* Make sure the stream class is part of the writer's trace */
- stream_class_count = bt_ctf_trace_get_stream_class_count(writer->trace);
- if (stream_class_count < 0) {
- goto error;
- }
-
- for (i = 0; i < stream_class_count; i++) {
- struct bt_ctf_stream_class *existing_stream_class =
- bt_ctf_trace_get_stream_class_by_index(
- writer->trace, i);
-
- if (existing_stream_class == stream_class) {
- stream_class_found = BT_TRUE;
- }
-
- BT_CTF_OBJECT_PUT_REF_AND_RESET(existing_stream_class);
-
- if (stream_class_found) {
- break;
- }
- }
-
- if (!stream_class_found) {
- int ret = bt_ctf_trace_add_stream_class(writer->trace,
- stream_class);
-
- if (ret) {
- goto error;
- }
- }
-
- stream = bt_ctf_stream_create_with_id(stream_class, NULL, -1ULL);
- if (!stream) {
- goto error;
- }
-
- return stream;
-
-error:
- BT_CTF_OBJECT_PUT_REF_AND_RESET(stream);
- return stream;
-}
-
-int bt_ctf_writer_add_environment_field(struct bt_ctf_writer *writer,
- const char *name,
- const char *value)
-{
- int ret = -1;
-
- if (!writer || !name || !value) {
- goto end;
- }
-
- ret = bt_ctf_trace_set_environment_field_string(writer->trace,
- name, value);
-end:
- return ret;
-}
-
-int bt_ctf_writer_add_environment_field_int64(struct bt_ctf_writer *writer,
- const char *name, int64_t value)
-{
- int ret = -1;
-
- if (!writer || !name) {
- goto end;
- }
-
- ret = bt_ctf_trace_set_environment_field_integer(writer->trace, name,
- value);
-end:
- return ret;
-}
-
-int bt_ctf_writer_add_clock(struct bt_ctf_writer *writer,
- struct bt_ctf_clock *clock)
-{
- int ret = -1;
-
- if (!writer || !clock) {
- goto end;
- }
-
- ret = bt_ctf_trace_add_clock_class(writer->trace, clock->clock_class);
-end:
- return ret;
-}
-
-char *bt_ctf_writer_get_metadata_string(struct bt_ctf_writer *writer)
-{
- char *metadata_string = NULL;
-
- if (!writer) {
- goto end;
- }
-
- metadata_string = bt_ctf_trace_get_metadata_string(
- writer->trace);
-end:
- return metadata_string;
-}
-
-void bt_ctf_writer_flush_metadata(struct bt_ctf_writer *writer)
-{
- int ret;
- char *metadata_string = NULL;
-
- if (!writer) {
- goto end;
- }
-
- metadata_string = bt_ctf_trace_get_metadata_string(
- writer->trace);
- if (!metadata_string) {
- goto end;
- }
-
- if (lseek(writer->metadata_fd, 0, SEEK_SET) == (off_t)-1) {
- perror("lseek");
- goto end;
- }
-
- if (ftruncate(writer->metadata_fd, 0)) {
- perror("ftruncate");
- goto end;
- }
-
- ret = write(writer->metadata_fd, metadata_string,
- strlen(metadata_string));
- if (ret < 0) {
- perror("write");
- goto end;
- }
-end:
- g_free(metadata_string);
-}
-
-int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
- enum bt_ctf_byte_order byte_order)
-{
- int ret = 0;
-
- if (!writer || writer->frozen) {
- ret = -1;
- goto end;
- }
-
- if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- if (BYTE_ORDER == LITTLE_ENDIAN) {
- byte_order = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
- } else {
- byte_order = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
- }
- }
-
- ret = bt_ctf_trace_set_native_byte_order(writer->trace,
- byte_order);
-end:
- return ret;
-}
-
-BT_HIDDEN
-void bt_ctf_writer_freeze(struct bt_ctf_writer *writer)
-{
- writer->frozen = 1;
-}
-
-static
-const unsigned int field_type_aliases_alignments[] = {
- [FIELD_TYPE_ALIAS_UINT5_T] = 1,
- [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
- [FIELD_TYPE_ALIAS_UINT27_T] = 1,
- [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
-};
-
-static
-const unsigned int field_type_aliases_sizes[] = {
- [FIELD_TYPE_ALIAS_UINT5_T] = 5,
- [FIELD_TYPE_ALIAS_UINT8_T] = 8,
- [FIELD_TYPE_ALIAS_UINT16_T] = 16,
- [FIELD_TYPE_ALIAS_UINT27_T] = 27,
- [FIELD_TYPE_ALIAS_UINT32_T] = 32,
- [FIELD_TYPE_ALIAS_UINT64_T] = 64,
-};
-
-BT_HIDDEN
-struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
-{
- int ret;
- unsigned int alignment, size;
- struct bt_ctf_field_type *field_type = NULL;
-
- if (alias >= NR_FIELD_TYPE_ALIAS) {
- goto end;
- }
-
- alignment = field_type_aliases_alignments[alias];
- size = field_type_aliases_sizes[alias];
- field_type = bt_ctf_field_type_integer_create(size);
- ret = bt_ctf_field_type_set_alignment(field_type, alignment);
- if (ret) {
- BT_CTF_OBJECT_PUT_REF_AND_RESET(field_type);
- }
-end:
- return field_type;
-}
-
-BT_HIDDEN
-const char *bt_ctf_get_byte_order_string(enum bt_ctf_byte_order byte_order)
-{
- const char *string;
-
- switch (byte_order) {
- case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
- string = "le";
- break;
- case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
- string = "be";
- break;
- case BT_CTF_BYTE_ORDER_NATIVE:
- string = "native";
- break;
- default:
- abort();
- }
-
- return string;
-}
libtestcommon_la_SOURCES = common.c common.h
noinst_LTLIBRARIES = libtestcommon.la
-# -Wl,--no-as-needed is needed for recent gold linker who seems to think
-# it knows better and considers libraries with constructors having
-# side-effects as dead code.
-COMMON_TEST_LDADD = $(LIBTAP) $(builddir)/libtestcommon.la \
- $(top_builddir)/lib/libbabeltrace2.la
+COMMON_TEST_LDADD = $(LIBTAP) $(builddir)/libtestcommon.la
test_bitfield_LDADD = $(LIBTAP) $(builddir)/libtestcommon.la
-test_ctf_writer_LDADD = $(COMMON_TEST_LDADD)
+test_ctf_writer_LDADD = \
+ $(COMMON_TEST_LDADD) \
+ $(top_builddir)/ctf-writer/libbabeltrace2-ctf-writer.la
-test_bt_values_LDADD = $(COMMON_TEST_LDADD)
+test_bt_values_LDADD = $(COMMON_TEST_LDADD) \
+ $(top_builddir)/lib/libbabeltrace2.la
-test_trace_ir_ref_LDADD = $(COMMON_TEST_LDADD)
+test_trace_ir_ref_LDADD = $(COMMON_TEST_LDADD) \
+ $(top_builddir)/lib/libbabeltrace2.la \
+ $(top_builddir)/ctf-writer/libbabeltrace2-ctf-writer.la
-test_graph_topo_LDADD = $(COMMON_TEST_LDADD)
+test_graph_topo_LDADD = $(COMMON_TEST_LDADD) \
+ $(top_builddir)/lib/libbabeltrace2.la
noinst_PROGRAMS = test_bitfield test_ctf_writer test_bt_values \
test_trace_ir_ref test_graph_topo
if !ENABLE_BUILT_IN_PLUGINS
noinst_PROGRAMS += test_plugin
-test_plugin_LDADD = $(COMMON_TEST_LDADD)
+test_plugin_LDADD = $(COMMON_TEST_LDADD) \
+ $(top_builddir)/lib/libbabeltrace2.la
test_plugin_SOURCES = test_plugin.c
SUBDIRS += test-plugin-plugins
endif
#include <babeltrace2/object-internal.h>
#include <babeltrace2/compat/stdlib-internal.h>
#include <babeltrace2/assert-internal.h>
+#include <babeltrace2/ctf-writer/writer.h>
+#include <babeltrace2/ctf-writer/clock.h>
+#include <babeltrace2/ctf-writer/clock-class.h>
+#include <babeltrace2/ctf-writer/stream.h>
+#include <babeltrace2/ctf-writer/event.h>
+#include <babeltrace2/ctf-writer/event-types.h>
+#include <babeltrace2/ctf-writer/event-fields.h>
+#include <babeltrace2/ctf-writer/stream-class.h>
+#include <babeltrace2/ctf-writer/trace.h>
#include "common.h"
#define NR_TESTS 37