}
/* format (PRI*64) */
- if (strncmp(fmt_ch, PRId64, sizeof(PRId64)) == 0) {
+ if (strncmp(fmt_ch, PRId64, sizeof(PRId64) - 1) == 0) {
fmt_ch += sizeof(PRId64);
BUF_STD_APPEND_SINGLE_ARG(int64_t);
goto update_rw_fmt;
- } else if (strncmp(fmt_ch, PRIu64, sizeof(PRIu64)) == 0) {
+ } else if (strncmp(fmt_ch, PRIu64, sizeof(PRIu64) - 1) == 0) {
fmt_ch += sizeof(PRIu64);
BUF_STD_APPEND_SINGLE_ARG(uint64_t);
goto update_rw_fmt;
- } else if (strncmp(fmt_ch, PRIx64, sizeof(PRIx64)) == 0) {
+ } else if (strncmp(fmt_ch, PRIx64, sizeof(PRIx64) - 1) == 0) {
fmt_ch += sizeof(PRIx64);
BUF_STD_APPEND_SINGLE_ARG(uint64_t);
goto update_rw_fmt;
- } else if (strncmp(fmt_ch, PRIX64, sizeof(PRIX64)) == 0) {
+ } else if (strncmp(fmt_ch, PRIX64, sizeof(PRIX64) - 1) == 0) {
fmt_ch += sizeof(PRIX64);
BUF_STD_APPEND_SINGLE_ARG(uint64_t);
goto update_rw_fmt;
- } else if (strncmp(fmt_ch, PRIo64, sizeof(PRIo64)) == 0) {
+ } else if (strncmp(fmt_ch, PRIo64, sizeof(PRIo64) - 1) == 0) {
fmt_ch += sizeof(PRIo64);
BUF_STD_APPEND_SINGLE_ARG(uint64_t);
goto update_rw_fmt;
- } else if (strncmp(fmt_ch, PRIi64, sizeof(PRIi64)) == 0) {
+ } else if (strncmp(fmt_ch, PRIi64, sizeof(PRIi64) - 1) == 0) {
fmt_ch += sizeof(PRIi64);
BUF_STD_APPEND_SINGLE_ARG(int64_t);
goto update_rw_fmt;
babeltrace/ctf-ir/packet-header-field.h \
babeltrace/ctf-ir/stream-class.h \
babeltrace/ctf-ir/stream.h \
- babeltrace/ctf-ir/trace.h \
- babeltrace/ctf-ir/utils.h \
- babeltrace/ctf-ir/visitor.h
+ babeltrace/ctf-ir/trace.h
# Plugin and plugin development API
babeltracepluginincludedir = "$(includedir)/babeltrace/plugin"
babeltrace/ctf-ir/packet-internal.h \
babeltrace/ctf-ir/event-class-internal.h \
babeltrace/ctf-ir/utils-internal.h \
- babeltrace/ctf-ir/validation-internal.h \
babeltrace/ctf-ir/fields-internal.h \
babeltrace/ctf-ir/stream-class-internal.h \
babeltrace/ctf-ir/event-internal.h \
babeltrace/ctf-ir/clock-class-internal.h \
babeltrace/ctf-ir/field-types-internal.h \
babeltrace/ctf-ir/clock-value-internal.h \
- babeltrace/ctf-ir/clock-value-set-internal.h \
babeltrace/ctf-ir/attributes-internal.h \
babeltrace/ctf-ir/stream-internal.h \
- babeltrace/ctf-ir/resolve-internal.h \
- babeltrace/ctf-ir/visitor-internal.h \
+ babeltrace/ctf-ir/resolve-field-path-internal.h \
babeltrace/prio-heap-internal.h \
babeltrace/lib-logging-internal.h \
babeltrace/compiler-internal.h \
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/ctf-ir/utils.h>
-#include <babeltrace/ctf-ir/visitor.h>
/* Plugin and plugin development API */
#include <babeltrace/plugin/plugin-dev.h>
#include <babeltrace/ctf-ir/field-path.h>
#include <babeltrace/ctf-ir/event-class.h>
#include <stdarg.h>
+#include <inttypes.h>
+#include <stdint.h>
#include <glib.h>
#define BT_COMMON_COLOR_RESET "\033[0m"
const char *bt_common_field_type_id_string(enum bt_field_type_id type_id)
{
switch (type_id) {
- case BT_FIELD_TYPE_ID_UNKNOWN:
- return "BT_FIELD_TYPE_ID_UNKNOWN";
- case BT_FIELD_TYPE_ID_INTEGER:
- return "BT_FIELD_TYPE_ID_INTEGER";
- case BT_FIELD_TYPE_ID_FLOAT:
- return "BT_FIELD_TYPE_ID_FLOAT";
- case BT_FIELD_TYPE_ID_ENUM:
- return "BT_FIELD_TYPE_ID_ENUM";
+ case BT_FIELD_TYPE_ID_UNSIGNED_INTEGER:
+ return "BT_FIELD_TYPE_ID_UNSIGNED_INTEGER";
+ case BT_FIELD_TYPE_ID_SIGNED_INTEGER:
+ return "BT_FIELD_TYPE_ID_SIGNED_INTEGER";
+ case BT_FIELD_TYPE_ID_REAL:
+ return "BT_FIELD_TYPE_ID_REAL";
+ case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION:
+ return "BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION";
+ case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION:
+ return "BT_FIELD_TYPE_ID_SIGNED_ENUMERATION";
case BT_FIELD_TYPE_ID_STRING:
return "BT_FIELD_TYPE_ID_STRING";
- case BT_FIELD_TYPE_ID_STRUCT:
- return "BT_FIELD_TYPE_ID_STRUCT";
- case BT_FIELD_TYPE_ID_ARRAY:
- return "BT_FIELD_TYPE_ID_ARRAY";
- case BT_FIELD_TYPE_ID_SEQUENCE:
- return "BT_FIELD_TYPE_ID_SEQUENCE";
+ case BT_FIELD_TYPE_ID_STRUCTURE:
+ return "BT_FIELD_TYPE_ID_STRUCTURE";
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ return "BT_FIELD_TYPE_ID_STATIC_ARRAY";
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ return "BT_FIELD_TYPE_ID_DYNAMIC_ARRAY";
case BT_FIELD_TYPE_ID_VARIANT:
return "BT_FIELD_TYPE_ID_VARIANT";
default:
};
static inline
-const char *bt_common_byte_order_string(enum bt_byte_order bo)
-{
- switch (bo) {
- case BT_BYTE_ORDER_UNKNOWN:
- return "BT_BYTE_ORDER_UNKNOWN";
- case BT_BYTE_ORDER_UNSPECIFIED:
- return "BT_BYTE_ORDER_UNSPECIFIED";
- case BT_BYTE_ORDER_NATIVE:
- return "BT_BYTE_ORDER_NATIVE";
- case BT_BYTE_ORDER_LITTLE_ENDIAN:
- return "BT_BYTE_ORDER_LITTLE_ENDIAN";
- case BT_BYTE_ORDER_BIG_ENDIAN:
- return "BT_BYTE_ORDER_BIG_ENDIAN";
- case BT_BYTE_ORDER_NETWORK:
- return "BT_BYTE_ORDER_NETWORK";
- default:
- return "(unknown)";
- }
-};
-
-static inline
-const char *bt_common_string_encoding_string(enum bt_string_encoding encoding)
-{
- switch (encoding) {
- case BT_STRING_ENCODING_UNKNOWN:
- return "BT_STRING_ENCODING_UNKNOWN";
- case BT_STRING_ENCODING_NONE:
- return "BT_STRING_ENCODING_NONE";
- case BT_STRING_ENCODING_UTF8:
- return "BT_STRING_ENCODING_UTF8";
- case BT_STRING_ENCODING_ASCII:
- return "BT_STRING_ENCODING_ASCII";
- default:
- return "(unknown)";
- }
-};
-
-static inline
-const char *bt_common_integer_base_string(enum bt_integer_base base)
+const char *bt_common_field_type_integer_preferred_display_base_string(enum bt_field_type_integer_preferred_display_base base)
{
switch (base) {
- case BT_INTEGER_BASE_UNKNOWN:
- return "BT_INTEGER_BASE_UNKNOWN";
- case BT_INTEGER_BASE_UNSPECIFIED:
- return "BT_INTEGER_BASE_UNSPECIFIED";
- case BT_INTEGER_BASE_BINARY:
- return "BT_INTEGER_BASE_BINARY";
- case BT_INTEGER_BASE_OCTAL:
- return "BT_INTEGER_BASE_OCTAL";
- case BT_INTEGER_BASE_DECIMAL:
- return "BT_INTEGER_BASE_DECIMAL";
- case BT_INTEGER_BASE_HEXADECIMAL:
- return "BT_INTEGER_BASE_HEXADECIMAL";
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
+ return "BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY";
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
+ return "BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL";
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL:
+ return "BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL";
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
+ return "BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL";
default:
return "(unknown)";
}
const char *bt_common_scope_string(enum bt_scope scope)
{
switch (scope) {
- case BT_SCOPE_UNKNOWN:
- return "BT_SCOPE_UNKNOWN";
- case BT_SCOPE_TRACE_PACKET_HEADER:
- return "BT_SCOPE_TRACE_PACKET_HEADER";
- case BT_SCOPE_STREAM_PACKET_CONTEXT:
- return "BT_SCOPE_STREAM_PACKET_CONTEXT";
- case BT_SCOPE_STREAM_EVENT_HEADER:
- return "BT_SCOPE_STREAM_EVENT_HEADER";
- case BT_SCOPE_STREAM_EVENT_CONTEXT:
- return "BT_SCOPE_STREAM_EVENT_CONTEXT";
- case BT_SCOPE_EVENT_CONTEXT:
- return "BT_SCOPE_EVENT_CONTEXT";
+ case BT_SCOPE_PACKET_HEADER:
+ return "BT_SCOPE_PACKET_HEADER";
+ case BT_SCOPE_PACKET_CONTEXT:
+ return "BT_SCOPE_PACKET_CONTEXT";
+ case BT_SCOPE_EVENT_HEADER:
+ return "BT_SCOPE_EVENT_HEADER";
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ return "BT_SCOPE_EVENT_COMMON_CONTEXT";
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ return "BT_SCOPE_EVENT_SPECIFIC_CONTEXT";
case BT_SCOPE_EVENT_PAYLOAD:
return "BT_SCOPE_EVENT_PAYLOAD";
- case BT_SCOPE_ENV:
- return "BT_SCOPE_ENV";
default:
return "(unknown)";
}
enum bt_event_class_log_level level)
{
switch (level) {
- case BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN:
- return "BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN";
- case BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
- return "BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED";
case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
return "BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY";
case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
GString *bt_field_path_string(struct bt_field_path *path)
{
GString *str = g_string_new(NULL);
- size_t i;
+ uint64_t i;
BT_ASSERT(path);
bt_field_path_get_root_scope(path)));
for (i = 0; i < bt_field_path_get_index_count(path); i++) {
- int index = bt_field_path_get_index(path, i);
-
- g_string_append_printf(str, ", %d", index);
+ g_string_append_printf(str, ", %" PRIu64,
+ bt_field_path_get_index_by_index(path, i));
}
g_string_append(str, "]");
#include <babeltrace/object-pool-internal.h>
#include <babeltrace/compat/uuid-internal.h>
#include <babeltrace/types.h>
+#include <babeltrace/property-internal.h>
#include <stdbool.h>
#include <stdint.h>
#include <glib.h>
struct bt_clock_class {
struct bt_object base;
- GString *name;
- GString *description;
+
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } name;
+
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } description;
+
uint64_t frequency;
uint64_t precision;
- int64_t offset_s; /* Offset in seconds */
- int64_t offset; /* Offset in ticks */
- unsigned char uuid[BABELTRACE_UUID_LEN];
- int uuid_set;
- int absolute;
+ int64_t offset_seconds;
+ uint64_t offset_cycles;
+
+ struct {
+ uint8_t uuid[BABELTRACE_UUID_LEN];
+
+ /* NULL or `uuid` above */
+ bt_uuid value;
+ } uuid;
+
+ bool is_absolute;
/*
- * A clock's properties can't be modified once it is added to a stream
- * class.
+ * This is computed every time you call
+ * bt_clock_class_set_frequency() or
+ * bt_clock_class_set_offset(), as well as initially. It is the
+ * base offset in nanoseconds including both `offset_seconds`
+ * and `offset_cycles` above in the result. It is used to
+ * accelerate future calls to
+ * bt_clock_value_get_ns_from_origin() and
+ * bt_clock_class_cycles_to_ns_from_origin().
+ *
+ * `overflows` is true if the base offset cannot be computed
+ * because of an overflow.
*/
- int frozen;
+ struct {
+ int64_t value_ns;
+ bool overflows;
+ } base_offset;
/* Pool of `struct bt_clock_value *` */
struct bt_object_pool cv_pool;
+
+ bool frozen;
};
BT_HIDDEN
-void bt_clock_class_freeze(struct bt_clock_class *clock_class);
+void _bt_clock_class_freeze(struct bt_clock_class *clock_class);
-BT_HIDDEN
-bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class);
+#ifdef BT_DEV_MODE
+# define bt_clock_class_freeze _bt_clock_class_freeze
+#else
+# define bt_clock_class_freeze(_cc)
+#endif
BT_HIDDEN
-int bt_clock_class_compare(struct bt_clock_class *clock_class_a,
- struct bt_clock_class *clock_class_b);
+bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class);
#endif /* BABELTRACE_CTF_IR_CLOCK_CLASS_INTERNAL_H */
* BabelTrace - CTF IR: Clock class
*
* Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
*
* Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
*
#include <stdint.h>
-/* For bt_bool */
+/* For bt_bool, bt_uuid */
#include <babeltrace/types.h>
#ifdef __cplusplus
struct bt_clock_class;
struct bt_clock_value;
-extern struct bt_clock_class *bt_clock_class_create(const char *name,
- uint64_t freq);
-extern const char *bt_clock_class_get_name(
- struct bt_clock_class *clock_class);
+extern struct bt_clock_class *bt_clock_class_create(void);
+
+extern const char *bt_clock_class_get_name(struct bt_clock_class *clock_class);
+
extern int bt_clock_class_set_name(struct bt_clock_class *clock_class,
const char *name);
+
extern const char *bt_clock_class_get_description(
struct bt_clock_class *clock_class);
-extern int bt_clock_class_set_description(
- struct bt_clock_class *clock_class,
- const char *desc);
+
+extern int bt_clock_class_set_description(struct bt_clock_class *clock_class,
+ const char *description);
+
extern uint64_t bt_clock_class_get_frequency(
struct bt_clock_class *clock_class);
-extern int bt_clock_class_set_frequency(
- struct bt_clock_class *clock_class, uint64_t freq);
+
+extern int bt_clock_class_set_frequency(struct bt_clock_class *clock_class,
+ uint64_t freq);
+
extern uint64_t bt_clock_class_get_precision(
struct bt_clock_class *clock_class);
-extern int bt_clock_class_set_precision(
- struct bt_clock_class *clock_class, uint64_t precision);
-extern int bt_clock_class_get_offset_s(
- struct bt_clock_class *clock_class, int64_t *seconds);
-extern int bt_clock_class_set_offset_s(
- struct bt_clock_class *clock_class, int64_t seconds);
-extern int bt_clock_class_get_offset_cycles(
- struct bt_clock_class *clock_class, int64_t *cycles);
-extern int bt_clock_class_set_offset_cycles(
- struct bt_clock_class *clock_class, int64_t cycles);
-extern bt_bool bt_clock_class_is_absolute(
- struct bt_clock_class *clock_class);
-extern int bt_clock_class_set_is_absolute(
- struct bt_clock_class *clock_class, bt_bool is_absolute);
-extern const unsigned char *bt_clock_class_get_uuid(
- struct bt_clock_class *clock_class);
+
+extern int bt_clock_class_set_precision(struct bt_clock_class *clock_class,
+ uint64_t precision);
+
+extern void bt_clock_class_get_offset(struct bt_clock_class *clock_class,
+ int64_t *seconds, uint64_t *cycles);
+
+extern int bt_clock_class_set_offset(struct bt_clock_class *clock_class,
+ int64_t seconds, uint64_t cycles);
+
+extern bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class);
+
+extern int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class,
+ bt_bool is_absolute);
+
+extern bt_uuid bt_clock_class_get_uuid(struct bt_clock_class *clock_class);
+
extern int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
- const unsigned char *uuid);
-extern int bt_clock_class_cycles_to_ns(struct bt_clock_class *clock_class,
- uint64_t cycles, int64_t *ns);
+ bt_uuid uuid);
+
+extern int bt_clock_class_cycles_to_ns_from_origin(
+ struct bt_clock_class *clock_class,
+ uint64_t cycles, int64_t *ns_from_origin);
#ifdef __cplusplus
}
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
#include <stdbool.h>
#include <stdint.h>
struct bt_clock_value {
struct bt_object base;
struct bt_clock_class *clock_class;
- uint64_t value;
- bool ns_from_epoch_overflows;
- int64_t ns_from_epoch;
+ uint64_t value_cycles;
+ bool ns_from_origin_overflows;
+ int64_t ns_from_origin;
bool is_set;
- bool frozen;
};
static inline
clock_value->is_set = false;
}
-BT_UNUSED
static inline
-void _bt_clock_value_set_is_frozen(struct bt_clock_value *clock_value,
- bool is_frozen)
+void set_ns_from_origin(struct bt_clock_value *clock_value)
{
- BT_ASSERT(clock_value);
- clock_value->frozen = is_frozen;
-}
-
-static inline
-uint64_t ns_from_value(uint64_t frequency, uint64_t value)
-{
- uint64_t ns;
-
- if (frequency == UINT64_C(1000000000)) {
- ns = value;
- } else {
- double dblres = ((1e9 * (double) value) / (double) frequency);
-
- if (dblres >= (double) UINT64_MAX) {
- /* Overflows uint64_t */
- ns = -1ULL;
- } else {
- ns = (uint64_t) dblres;
- }
- }
-
- return ns;
-}
-
-static inline
-int ns_from_epoch(struct bt_clock_class *clock_class, uint64_t value,
- int64_t *ns_from_epoch, bool *overflows)
-{
- int ret = 0;
- int64_t diff;
- int64_t s_ns;
- uint64_t u_ns;
- uint64_t cycles;
-
- *overflows = false;
-
- /* Initialize nanosecond timestamp to clock's offset in seconds */
- if (clock_class->offset_s <= (INT64_MIN / INT64_C(1000000000)) ||
- clock_class->offset_s >= (INT64_MAX / INT64_C(1000000000))) {
- /*
- * Overflow: offset in seconds converted to nanoseconds
- * is outside the int64_t range.
- */
- *overflows = true;
- goto end;
- }
-
- *ns_from_epoch = clock_class->offset_s * INT64_C(1000000000);
-
- /* Add offset in cycles */
- if (clock_class->offset < 0) {
- cycles = (uint64_t) -clock_class->offset;
- } else {
- cycles = (uint64_t) clock_class->offset;
- }
-
- u_ns = ns_from_value(clock_class->frequency, cycles);
-
- if (u_ns == UINT64_C(-1) || u_ns >= INT64_MAX) {
- /*
- * Overflow: offset in cycles converted to nanoseconds
- * is outside the int64_t range.
- */
- *overflows = true;
- goto end;
- }
-
- s_ns = (int64_t) u_ns;
- BT_ASSERT(s_ns >= 0);
-
- if (clock_class->offset < 0) {
- if (*ns_from_epoch >= 0) {
- /*
- * Offset in cycles is negative so it must also
- * be negative once converted to nanoseconds.
- */
- s_ns = -s_ns;
- goto offset_ok;
- }
-
- diff = *ns_from_epoch - INT64_MIN;
-
- if (s_ns >= diff) {
- /*
- * Overflow: current timestamp in nanoseconds
- * plus the offset in cycles converted to
- * nanoseconds is outside the int64_t range.
- */
- *overflows = true;
- goto end;
- }
-
- /*
- * Offset in cycles is negative so it must also be
- * negative once converted to nanoseconds.
- */
- s_ns = -s_ns;
- } else {
- if (*ns_from_epoch <= 0) {
- goto offset_ok;
- }
-
- diff = INT64_MAX - *ns_from_epoch;
-
- if (s_ns >= diff) {
- /*
- * Overflow: current timestamp in nanoseconds
- * plus the offset in cycles converted to
- * nanoseconds is outside the int64_t range.
- */
- *overflows = true;
- goto end;
- }
- }
-
-offset_ok:
- *ns_from_epoch += s_ns;
-
- /* Add clock value (cycles) */
- u_ns = ns_from_value(clock_class->frequency, value);
-
- if (u_ns == -1ULL || u_ns >= INT64_MAX) {
- /*
- * Overflow: value converted to nanoseconds is outside
- * the int64_t range.
- */
- *overflows = true;
- goto end;
- }
-
- s_ns = (int64_t) u_ns;
- BT_ASSERT(s_ns >= 0);
-
- /* Clock value (cycles) is always positive */
- if (*ns_from_epoch <= 0) {
- goto value_ok;
- }
-
- diff = INT64_MAX - *ns_from_epoch;
-
- if (s_ns >= diff) {
- /*
- * Overflow: current timestamp in nanoseconds plus the
- * clock value converted to nanoseconds is outside the
- * int64_t range.
- */
- *overflows = true;
- goto end;
+ if (bt_util_ns_from_origin(clock_value->clock_class, clock_value->value_cycles,
+ &clock_value->ns_from_origin)) {
+ clock_value->ns_from_origin_overflows = true;
}
-value_ok:
- *ns_from_epoch += s_ns;
-
-end:
- if (*overflows) {
- *ns_from_epoch = 0;
- ret = -1;
- }
-
- return ret;
-}
-
-static inline
-void set_ns_from_epoch(struct bt_clock_value *clock_value)
-{
- (void) ns_from_epoch(clock_value->clock_class,
- clock_value->value, &clock_value->ns_from_epoch,
- &clock_value->ns_from_epoch_overflows);
}
static inline
uint64_t cycles)
{
BT_ASSERT(clock_value);
-
- clock_value->value = cycles;
- set_ns_from_epoch(clock_value);
+ clock_value->value_cycles = cycles;
+ set_ns_from_origin(clock_value);
bt_clock_value_set(clock_value);
}
static inline
-int bt_clock_value_set_value_inline(struct bt_clock_value *clock_value,
+void bt_clock_value_set_value_inline(struct bt_clock_value *clock_value,
uint64_t raw_value)
{
-#ifdef BT_ASSERT_PRE_NON_NULL
- BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
-#endif
-
-#ifdef BT_ASSERT_PRE_HOT
- BT_ASSERT_PRE_HOT(clock_value, "Clock value", ": %!+k", clock_value);
-#endif
-
bt_clock_value_set_raw_value(clock_value, raw_value);
- return 0;
}
-#ifdef BT_DEV_MODE
-# define bt_clock_value_set_is_frozen _bt_clock_value_set_is_frozen
-#else
-# define bt_clock_value_set_is_frozen(_x, _f)
-#endif /* BT_DEV_MODE */
+BT_HIDDEN
+void bt_clock_value_destroy(struct bt_clock_value *clock_value);
+
+BT_HIDDEN
+struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class);
BT_HIDDEN
struct bt_clock_value *bt_clock_value_create(
BT_ASSERT(cv);
bt_clock_value_reset(cv);
- bt_clock_value_set_is_frozen(cv, false);
}
cv_set->default_cv = NULL;
}
static inline
-int bt_clock_value_set_set_clock_value(
- struct bt_clock_value_set *cv_set,
- struct bt_clock_class *cc, uint64_t raw_value,
- bt_bool is_default)
+int bt_clock_value_set_set_clock_value(struct bt_clock_value_set *cv_set,
+ struct bt_clock_class *cc, uint64_t raw_value)
{
int ret = 0;
struct bt_clock_value *clock_value = NULL;
BT_ASSERT(cv_set);
BT_ASSERT(cc);
- /* Check if we already have a value for this clock class */
+ /*
+ * Check if we already have a value for this clock class.
+ *
+ * TODO: When we have many clock classes, make this more
+ * efficient.
+ */
for (i = 0; i < cv_set->clock_values->len; i++) {
struct bt_clock_value *cv = cv_set->clock_values->pdata[i];
g_ptr_array_add(cv_set->clock_values, clock_value);
}
-#ifdef BT_ASSERT_PRE_HOT
- BT_ASSERT_PRE_HOT(clock_value, "Clock value", ": %!+k", clock_value);
-#endif
-
- ret = bt_clock_value_set_value_inline(clock_value, raw_value);
- if (ret) {
- goto end;
- }
-
- if (is_default) {
- cv_set->default_cv = clock_value;
- }
+ bt_clock_value_set_value_inline(clock_value, raw_value);
end:
return ret;
}
+static inline
+void bt_clock_value_set_set_default_clock_value(
+ struct bt_clock_value_set *cv_set, uint64_t raw_value)
+{
+ BT_ASSERT(cv_set);
+ BT_ASSERT(cv_set->default_cv);
+ bt_clock_value_set_value_inline(cv_set->default_cv, raw_value);
+}
+
#endif /* BABELTRACE_GRAPH_CLOCK_VALUE_SET_H */
* http://www.efficios.com/ctf
*/
-/* For bt_get() */
-#include <babeltrace/ref.h>
-
#include <stdint.h>
#ifdef __cplusplus
struct bt_clock_class;
struct bt_clock_value;
-extern struct bt_clock_class *bt_clock_value_borrow_class(
+enum bt_clock_value_status {
+ BT_CLOCK_VALUE_STATUS_KNOWN,
+ BT_CLOCK_VALUE_STATUS_UNKNOWN,
+};
+
+extern struct bt_clock_class *bt_clock_value_borrow_clock_class(
struct bt_clock_value *clock_value);
-static inline
-struct bt_clock_class *bt_clock_value_get_class(
- struct bt_clock_value *clock_value)
-{
- return bt_get(bt_clock_value_borrow_class(clock_value));
-}
+extern uint64_t bt_clock_value_get_value(
+ struct bt_clock_value *clock_value);
-extern int bt_clock_value_get_value(
- struct bt_clock_value *clock_value, uint64_t *raw_value);
-extern int bt_clock_value_get_value_ns_from_epoch(
- struct bt_clock_value *clock_value, int64_t *value_ns);
+extern int bt_clock_value_get_ns_from_origin(
+ struct bt_clock_value *clock_value, int64_t *ns_from_origin);
#ifdef __cplusplus
}
#include <babeltrace/object-internal.h>
#include <babeltrace/assert-internal.h>
#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/property-internal.h>
#include <glib.h>
+#include <stdbool.h>
struct bt_event_class {
struct bt_object base;
- struct bt_field_type *context_field_type;
- struct bt_field_type *payload_field_type;
- int frozen;
+ struct bt_field_type *specific_context_ft;
+ struct bt_field_type *payload_ft;
- /*
- * This flag indicates if the event class is valid. A valid
- * event class is _always_ frozen. However, an event class
- * may be frozen, but not valid yet. This is okay, as long as
- * no events are created out of this event class.
- */
- int valid;
+ struct {
+ GString *str;
- /* Attributes */
- GString *name;
- int64_t id;
- int log_level;
- GString *emf_uri;
+ /* NULL or `str->str` above */
+ const char *value;
+ } name;
+
+ uint64_t id;
+ struct bt_property_uint log_level;
+
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } emf_uri;
/* Pool of `struct bt_event *` */
struct bt_object_pool event_pool;
+
+ bool frozen;
};
BT_HIDDEN
-void bt_event_class_freeze(struct bt_event_class *event_class);
+void _bt_event_class_freeze(struct bt_event_class *event_class);
-typedef struct bt_field_type *(*bt_field_type_structure_create_func)();
+#ifdef BT_DEV_MODE
+# define bt_event_class_freeze _bt_event_class_freeze
+#else
+# define bt_event_class_freeze(_ec)
+#endif
-BT_HIDDEN
-int bt_event_class_validate_single_clock_class(
- struct bt_event_class *event_class,
- struct bt_clock_class **expected_clock_class);
+static inline
+struct bt_stream_class *bt_event_class_borrow_stream_class_inline(
+ struct bt_event_class *event_class)
+{
+ BT_ASSERT(event_class);
+ return (void *) bt_object_borrow_parent(&event_class->base);
+}
#endif /* BABELTRACE_CTF_IR_EVENT_CLASS_INTERNAL_H */
* http://www.efficios.com/ctf
*/
-/* For bt_get() */
-#include <babeltrace/ref.h>
+/* For enum bt_property_availability */
+#include <babeltrace/property.h>
#include <stdint.h>
#include <stddef.h>
extern "C" {
#endif
-struct bt_value;
-
-/**
-@defgroup ctfireventclass CTF IR event class
-@ingroup ctfir
-@brief CTF IR event class.
-
-@code
-#include <babeltrace/ctf-ir/event-class.h>
-@endcode
-
-A CTF IR <strong><em>event class</em></strong> is a template that you
-can use to create concrete \link ctfirevent CTF IR events\endlink.
-
-An event class has the following properties:
-
-- A \b name.
-- A numeric \b ID (\em must be unique amongst all the event classes
- contained in the same
- \link ctfirstreamclass CTF IR stream class\endlink).
-- A optional <strong>log level</strong>.
-- An optional <strong>Eclipse Modeling Framework URI</strong>.
-
-A CTF IR event class owns two
-\link ctfirfieldtypes field types\endlink:
-
-- An optional <strong>event context</strong> field type, which
- represents the \c event.context CTF scope.
-- A mandatory <strong>event payload</strong> field type, which
- represents the \c event.fields CTF scope.
-
-Both field types \em must be structure field types as of
-Babeltrace \btversion.
-The event payload field type <em>must not</em> be empty.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-In the Babeltrace CTF IR system, a \link ctfirtraceclass trace
-class\endlink contains zero or more \link ctfirstreamclass stream
-classes\endlink, and a stream class contains zero or more event classes.
-
-Before you can create an event from an event class with
-bt_event_create(), you \em must add the prepared event class to a
-stream class by calling bt_stream_class_add_event_class(). This
-function, when successful, \em freezes the event class, disallowing any
-future modification of its properties and field types by the user.
-
-As with any Babeltrace object, CTF IR event class objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-bt_stream_class_add_event_class() \em freezes its event class
-parameter on success. You cannot modify a frozen event class: it is
-considered immutable, except for \link refs reference counting\endlink.
-
-@sa ctfirevent
-@sa ctfirstreamclass
-
-@file
-@brief CTF IR event class type and functions.
-@sa ctfireventclass
-
-@addtogroup ctfireventclass
-@{
-*/
-
-/**
-@struct bt_event_class
-@brief A CTF IR event class.
-@sa ctfireventclass
-*/
struct bt_event_class;
-struct bt_field;
struct bt_field_type;
struct bt_stream_class;
-/**
-@brief Log level of an event class.
-*/
enum bt_event_class_log_level {
- /// Unknown, used for errors.
- BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN = -1,
-
- /// Unspecified log level.
- BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED = 255,
-
- /// System is unusable.
- BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY = 0,
-
- /// Action must be taken immediately.
- BT_EVENT_CLASS_LOG_LEVEL_ALERT = 1,
-
- /// Critical conditions.
- BT_EVENT_CLASS_LOG_LEVEL_CRITICAL = 2,
-
- /// Error conditions.
- BT_EVENT_CLASS_LOG_LEVEL_ERROR = 3,
-
- /// Warning conditions.
- BT_EVENT_CLASS_LOG_LEVEL_WARNING = 4,
-
- /// Normal, but significant, condition.
- BT_EVENT_CLASS_LOG_LEVEL_NOTICE = 5,
-
- /// Informational message.
- BT_EVENT_CLASS_LOG_LEVEL_INFO = 6,
-
- /// Debug information with system-level scope (set of programs).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM = 7,
-
- /// Debug information with program-level scope (set of processes).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM = 8,
-
- /// Debug information with process-level scope (set of modules).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS = 9,
-
- /// Debug information with module (executable/library) scope (set of units).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE = 10,
-
- /// Debug information with compilation unit scope (set of functions).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT = 11,
-
- /// Debug information with function-level scope.
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION = 12,
-
- /// Debug information with line-level scope (default log level).
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE = 13,
-
- /// Debug-level message.
- BT_EVENT_CLASS_LOG_LEVEL_DEBUG = 14,
+ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY,
+ BT_EVENT_CLASS_LOG_LEVEL_ALERT,
+ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL,
+ BT_EVENT_CLASS_LOG_LEVEL_ERROR,
+ BT_EVENT_CLASS_LOG_LEVEL_WARNING,
+ BT_EVENT_CLASS_LOG_LEVEL_NOTICE,
+ BT_EVENT_CLASS_LOG_LEVEL_INFO,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE,
+ BT_EVENT_CLASS_LOG_LEVEL_DEBUG,
};
-/**
-@name Creation and parent access functions
-@{
-*/
-
-/**
-@brief Creates a default CTF IR event class named \p nameÂ.
-
-On success, the context and payload field types are empty structure
-field types. You can modify those default field types after the
-event class is created with
-bt_event_class_set_context_field_type() and
-bt_event_class_set_payload_field_type().
-
-Upon creation, the event class's ID is <em>not set</em>. You
-can set it to a specific value with bt_event_class_set_id(). If it
-is still unset when you call bt_stream_class_add_event_class(), then
-the stream class assigns a unique ID to this event class before
-freezing it.
-
-The created event class's log level is initially set to
-#BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED and it has no Eclipse Modeling
-Framework URI.
+extern struct bt_event_class *bt_event_class_create(
+ struct bt_stream_class *stream_class);
-@param[in] name Name of the event class to create (copied on success).
-@returns Created event class, or \c NULL on error.
-
-@prenotnull{name}
-@postsuccessrefcountret1
-*/
-extern struct bt_event_class *bt_event_class_create(const char *name);
+extern struct bt_event_class *bt_event_class_create_with_id(
+ struct bt_stream_class *stream_class, uint64_t id);
extern struct bt_stream_class *bt_event_class_borrow_stream_class(
struct bt_event_class *event_class);
-/**
-@brief Returns the parent CTF IR stream class of the CTF IR event
- class \p event_class.
-
-It is possible that the event class was not added to a stream class
-yet, in which case this function returns \c NULL. You can add an
-event class to a stream class with
-bt_stream_class_add_event_class().
-
-@param[in] event_class Event class of which to get the parent
- stream class.
-@returns Parent stream class of \p event_class,
- or \c NULL if \p event_class was not
- added to a stream class yet or on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-@postsuccessrefcountretinc
-
-@sa bt_stream_class_add_event_class(): Add an event class to
- a stream class.
-*/
-static inline
-struct bt_stream_class *bt_event_class_get_stream_class(
- struct bt_event_class *event_class)
-{
- return bt_get(bt_event_class_borrow_stream_class(event_class));
-}
-
-/** @} */
-
-/**
-@name Attribute functions
-@{
-*/
-
-/**
-@brief Returns the name of the CTF IR event class \p event_class.
+extern const char *bt_event_class_get_name(struct bt_event_class *event_class);
-On success, \p event_class remains the sole owner of the returned
-string.
-
-@param[in] event_class Event class of which to get the name.
-@returns Name of event class \p event_class, or
- \c NULL on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-*/
-extern const char *bt_event_class_get_name(
- struct bt_event_class *event_class);
+extern int bt_event_class_set_name(struct bt_event_class *event_class,
+ const char *name);
-/**
-@brief Returns the numeric ID of the CTF IR event class \p event_class.
+extern uint64_t bt_event_class_get_id(struct bt_event_class *event_class);
-@param[in] event_class Event class of which to get the numeric ID.
-@returns ID of event class \p event_class, or a
- negative value on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-
-@sa bt_event_class_set_id(): Sets the numeric ID of a given
- event class.
-*/
-extern int64_t bt_event_class_get_id(
- struct bt_event_class *event_class);
-
-/**
-@brief Sets the numeric ID of the CTF IR event class
- \p event_class to \p id.
-
-\p id must be unique amongst the IDs of all the event classes
-of the stream class to which you eventually add \p event_class.
-
-@param[in] event_class Event class of which to set the numeric ID.
-@param[in] id ID of the event class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@prehot{event_class}
-@pre \p id is lesser than or equal to 9223372036854775807 (\c INT64_MAX).
-@postrefcountsame{event_class}
-
-@sa bt_event_class_get_id(): Returns the numeric ID of a given
- event class.
-*/
-extern int bt_event_class_set_id(
- struct bt_event_class *event_class, uint64_t id);
-
-/**
-@brief Returns the log level of the CTF IR event class \p event_class.
-
-@param[in] event_class Event class of which to get the log level.
-@returns Log level of event class \p event_class,
- #BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED if
- not specified, or
- #BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-
-@sa bt_event_class_set_log_level(): Sets the log level of a given
- event class.
-*/
-extern enum bt_event_class_log_level bt_event_class_get_log_level(
- struct bt_event_class *event_class);
-
-/**
-@brief Sets the log level of the CTF IR event class
- \p event_class to \p log_level.
-
-@param[in] event_class Event class of which to set the log level.
-@param[in] log_level Log level of the event class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@prehot{event_class}
-@pre \p log_level is #BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED,
- #BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY,
- #BT_EVENT_CLASS_LOG_LEVEL_ALERT,
- #BT_EVENT_CLASS_LOG_LEVEL_CRITICAL,
- #BT_EVENT_CLASS_LOG_LEVEL_ERROR,
- #BT_EVENT_CLASS_LOG_LEVEL_WARNING,
- #BT_EVENT_CLASS_LOG_LEVEL_NOTICE,
- #BT_EVENT_CLASS_LOG_LEVEL_INFO,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION,
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE, or
- #BT_EVENT_CLASS_LOG_LEVEL_DEBUG.
-@postrefcountsame{event_class}
-
-@sa bt_event_class_get_log_level(): Returns the log level of a given
- event class.
-*/
-extern int bt_event_class_set_log_level(
+extern enum bt_property_availability bt_event_class_get_log_level(
struct bt_event_class *event_class,
- enum bt_event_class_log_level log_level);
-
-/**
-@brief Returns the Eclipse Modeling Framework URI of the CTF IR event
- class \p event_class.
+ enum bt_event_class_log_level *log_level);
-@param[in] event_class Event class of which to get the
- Eclipse Modeling Framework URI.
-@returns Eclipse Modeling Framework URI of event
- class \p event_class, or \c NULL on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
+extern int bt_event_class_set_log_level(struct bt_event_class *event_class,
+ enum bt_event_class_log_level log_level);
-@sa bt_event_class_set_emf_uri(): Sets the Eclipse Modeling
- Framework URI of a given event class.
-*/
extern const char *bt_event_class_get_emf_uri(
struct bt_event_class *event_class);
-/**
-@brief Sets the Eclipse Modeling Framework URI of the CTF IR event class
- \p event_class to \p emf_uri, or unsets the event class's EMF URI.
-
-@param[in] event_class Event class of which to set the
- Eclipse Modeling Framework URI.
-@param[in] emf_uri Eclipse Modeling Framework URI of the
- event class (copied on success), or \c NULL
- to unset the current EMF URI.
-@returns 0 on success, or a negative value if there's
- no EMF URI or on error.
-
-@prenotnull{event_class}
-@prenotnull{emf_uri}
-@prehot{event_class}
-@postrefcountsame{event_class}
-
-@sa bt_event_class_get_emf_uri(): Returns the Eclipse Modeling
- Framework URI of a given event class.
-*/
-extern int bt_event_class_set_emf_uri(
- struct bt_event_class *event_class,
+extern int bt_event_class_set_emf_uri(struct bt_event_class *event_class,
const char *emf_uri);
-/** @} */
-
-/**
-@name Contained field types functions
-@{
-*/
-
-extern struct bt_field_type *bt_event_class_borrow_context_field_type(
+extern struct bt_field_type *bt_event_class_borrow_specific_context_field_type(
struct bt_event_class *event_class);
-/**
-@brief Returns the context field type of the CTF IR event class
- \p event_class.
-
-@param[in] event_class Event class of which to get the context field type.
-@returns Context field type of \p event_class, or \c NULL if
- \p event_class has no context field type or on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-@post <strong>On success, if the return value is a field type</strong>, its
- reference count is incremented.
-
-@sa bt_event_class_set_context_field_type(): Sets the context field type of a
- given event class.
-*/
-static inline
-struct bt_field_type *bt_event_class_get_context_field_type(
- struct bt_event_class *event_class)
-{
- return bt_get(bt_event_class_borrow_context_field_type(event_class));
-}
-
-/**
-@brief Sets the context field type of the CTF IR event class \p event_class to
- \p context_type, or unsets the current context field type from
- \p event_class.
-
-If \p context_type is \c NULL, then this function unsets the current context
-field type from \p event_class, effectively making \p event_class an event class
-without a context field type.
-
-As of Babeltrace \btversion, if \p context_type is not \c NULL,
-\p context_type \em must be a CTF IR structure field type object.
-
-@param[in] event_class Event class of which to set the context field
- type.
-@param[in] context_type Context field type, or \c NULL to unset the
- current context field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@prehot{event_class}
-@pre <strong>If \p context_type is not \c NULL</strong>, \p context_type is a
- CTF IR structure field type.
-@postrefcountsame{event_class}
-@post <strong>On success, if \p context_type is not \c NULL</strong>,
- the reference count of \p context_type is incremented.
-
-@sa bt_event_class_get_context_field_type(): Returns the context field type of a
- given event class.
-*/
-extern int bt_event_class_set_context_field_type(
+extern int bt_event_class_set_specific_context_field_type(
struct bt_event_class *event_class,
- struct bt_field_type *context_type);
+ struct bt_field_type *field_type);
extern struct bt_field_type *bt_event_class_borrow_payload_field_type(
struct bt_event_class *event_class);
-/**
-@brief Returns the payload field type of the CTF IR event class
- \p event_class.
-
-@param[in] event_class Event class of which to get the payload field type.
-@returns Payload field type of \p event_class, or \c NULL if
- \p event_class has no payload field type or on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-@post <strong>On success, if the return value is a field type</strong>, its
- reference count is incremented.
-
-@sa bt_event_class_set_payload_field_type(): Sets the payload field type of a
- given event class.
-*/
-static inline
-struct bt_field_type *bt_event_class_get_payload_field_type(
- struct bt_event_class *event_class)
-{
- return bt_get(bt_event_class_borrow_payload_field_type(event_class));
-}
-
-/**
-@brief Sets the payload field type of the CTF IR event class \p event_class to
- \p payload_type, or unsets the current payload field type from
- \p event_class.
-
-If \p payload_type is \c NULL, then this function unsets the current payload
-field type from \p event_class, effectively making \p event_class an event class
-without a payload field type.
-
-As of Babeltrace \btversion, if \p payload_type is not \c NULL,
-\p payload_type \em must be a CTF IR structure field type object.
-
-@param[in] event_class Event class of which to set the payload field
- type.
-@param[in] payload_type Payload field type, or \c NULL to unset the
- current payload field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@prehot{event_class}
-@pre <strong>If \p payload_type is not \c NULL</strong>, \p payload_type is a
- CTF IR structure field type.
-@postrefcountsame{event_class}
-@post <strong>On success, if \p payload_type is not \c NULL</strong>,
- the reference count of \p payload_type is incremented.
-
-@sa bt_event_class_get_payload_field_type(): Returns the payload field type of a
- given event class.
-*/
extern int bt_event_class_set_payload_field_type(
struct bt_event_class *event_class,
- struct bt_field_type *payload_type);
-
-/** @} */
-
-/** @} */
+ struct bt_field_type *field_type);
#ifdef __cplusplus
}
extern "C" {
#endif
+struct bt_stream_class;
struct bt_event_header_field;
struct bt_field;
+extern
+struct bt_event_header_field *bt_event_header_field_create(
+ struct bt_stream_class *stream_class);
+
extern
struct bt_field *bt_event_header_field_borrow_field(
struct bt_event_header_field *field);
* SOFTWARE.
*/
+/* Protection: this file uses BT_LIB_LOG*() macros directly */
+#ifndef BABELTRACE_LIB_LOGGING_INTERNAL_H
+# error Please define include <babeltrace/lib-logging-internal.h> before including this file.
+#endif
+
#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/values.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/stream-internal.h>
#include <babeltrace/ctf-ir/fields.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
-#include <babeltrace/ctf-ir/clock-value-set-internal.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/assert-internal.h>
#include <glib.h>
-struct bt_stream_pos;
+#define BT_ASSERT_PRE_EVENT_HOT(_event) \
+ BT_ASSERT_PRE_HOT((_event), "Event", ": %!+e", (_event))
struct bt_event {
struct bt_object base;
struct bt_event_class *class;
+ struct bt_packet *packet;
struct bt_field_wrapper *header_field;
- struct bt_field *stream_event_context_field;
- struct bt_field *context_field;
+ struct bt_field *common_context_field;
+ struct bt_field *specific_context_field;
struct bt_field *payload_field;
- struct bt_clock_value_set cv_set;
- struct bt_packet *packet;
- int frozen;
+ struct bt_clock_value *default_cv;
+ bool frozen;
};
BT_HIDDEN
# define bt_event_set_is_frozen(_event, _is_frozen)
#endif
-#define BT_ASSERT_PRE_EVENT_HOT(_event, _name) \
- BT_ASSERT_PRE_HOT((_event), (_name), ": %!+e", (_event))
-
-typedef void *(*create_field_func)(void *);
-typedef void (*release_field_func)(void *);
-typedef void *(*create_header_field_func)(void *, void *);
-typedef void (*release_header_field_func)(void *, void *);
-
BT_UNUSED
static inline
void _bt_event_reset_dev_mode(struct bt_event *event)
BT_ASSERT(event);
if (event->header_field) {
- bt_field_set_is_frozen_recursive(
+ bt_field_set_is_frozen(
event->header_field->field, false);
- bt_field_reset_recursive(
+ bt_field_reset(
event->header_field->field);
}
- if (event->stream_event_context_field) {
- bt_field_set_is_frozen_recursive(
- event->stream_event_context_field, false);
- bt_field_reset_recursive(
- event->stream_event_context_field);
+ if (event->common_context_field) {
+ bt_field_set_is_frozen(
+ event->common_context_field, false);
+ bt_field_reset(
+ event->common_context_field);
}
- if (event->context_field) {
- bt_field_set_is_frozen_recursive(
- event->context_field, false);
- bt_field_reset_recursive(event->context_field);
+ if (event->specific_context_field) {
+ bt_field_set_is_frozen(
+ event->specific_context_field, false);
+ bt_field_reset(event->specific_context_field);
}
if (event->payload_field) {
- bt_field_set_is_frozen_recursive(
+ bt_field_set_is_frozen(
event->payload_field, false);
- bt_field_reset_recursive(event->payload_field);
+ bt_field_reset(event->payload_field);
}
}
void bt_event_reset(struct bt_event *event)
{
BT_ASSERT(event);
+ BT_LIB_LOGD("Resetting event: %!+e", event);
bt_event_set_is_frozen(event, false);
- bt_clock_value_set_reset(&event->cv_set);
+
+ if (event->default_cv) {
+ bt_clock_value_reset(event->default_cv);
+ }
+
bt_object_put_no_null_check(&event->packet->base);
event->packet = NULL;
}
{
BT_ASSERT_PRE_NON_NULL(event, "Event");
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_EVENT_HOT(event, "Event");
+ BT_ASSERT_PRE_EVENT_HOT(event);
BT_ASSERT_PRE(bt_event_class_borrow_stream_class(
- event->class) == packet->stream->stream_class,
+ event->class) == packet->stream->class,
"Packet's stream class and event's stream class differ: "
- "%![event-]+e, %![packet-]+a",
- event, packet);
+ "%![event-]+e, %![packet-]+a", event, packet);
BT_ASSERT(!event->packet);
event->packet = packet;
bt_object_get_no_null_check_no_parent_check(&event->packet->base);
- BT_LOGV("Set event's packet: event-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
- "packet-addr=%p",
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class), packet);
+ BT_LIB_LOGV("Set event's packet: %![event-]+e, %![packet-]+a",
+ event, packet);
}
static inline
event = bt_object_pool_create_object(&event_class->event_pool);
if (unlikely(!event)) {
BT_LIB_LOGE("Cannot allocate one event from event class's event pool: "
- "%![event-class-]+E", event_class);
+ "%![ec-]+E", event_class);
goto end;
}
- if (unlikely(!event->class)) {
+ if (likely(!event->class)) {
event->class = event_class;
bt_object_get_no_null_check(&event_class->base);
}
* http://www.efficios.com/ctf
*/
-/* For bt_get() */
-#include <babeltrace/ref.h>
-
-/* For bt_bool */
-#include <babeltrace/types.h>
-
#include <stdint.h>
#include <stddef.h>
+/* For enum bt_clock_value_status */
+#include <babeltrace/ctf-ir/clock-value.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-struct bt_value;
-struct bt_clock_class;
-
-/**
-@defgroup ctfirevent CTF IR event
-@ingroup ctfir
-@brief CTF IR event.
-
-@code
-#include <babeltrace/ctf-ir/event.h>
-@endcode
-
-A CTF IR <strong><em>event</em></strong> is a container of event
-fields:
-
-- <strong>Stream event header</strong> field, described by the
- <em>stream event header field type</em> of a
- \link ctfirstreamclass CTF IR stream class\endlink.
-- <strong>Stream event context</strong> field, described by the
- <em>stream event context field type</em> of a stream class.
-- <strong>Event context</strong> field, described by the
- <em>event context field type</em> of a
- \link ctfireventclass CTF IR event class\endlink.
-- <strong>Event payload</strong>, described by the
- <em>event payload field type</em> of an event class.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-You can create a CTF IR event \em from a
-\link ctfireventclass CTF IR event class\endlink with
-bt_event_create(). The event class you use to create an event
-object becomes its parent.
-
-If the \link ctfirtraceclass CTF IR trace class\endlink of an event
-object (parent of its \link ctfirstreamclass CTF IR stream class\endlink,
-which is the parent of its event class) was created by a
-\link ctfwriter CTF writer\endlink object, then the only possible
-action you can do with this event object is to append it to a
-\link ctfirstream CTF IR stream\endlink with
-bt_stream_append_event(). Otherwise, you can create an event
-notification with bt_notification_event_create(). The event you pass
-to this function \em must have an attached packet object first.
-
-You can attach a \link ctfirpacket CTF IR packet object\endlink to an
-event object with bt_event_set_packet().
-
-A CTF IR event has a mapping of
-\link ctfirclockvalue CTF IR clock values\endlink. A clock value is
-an instance of a specific
-\link ctfirclockclass CTF IR clock class\endlink when the event is
-emitted. You can set an event object's clock value with
-bt_event_set_clock_value().
-
-As with any Babeltrace object, CTF IR event objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-bt_notification_event_create() \em freezes its event parameter on
-success. You cannot modify a frozen event object: it is considered
-immutable, except for \link refs reference counting\endlink.
-
-@sa ctfireventclass
-@sa ctfirpacket
-
-@file
-@brief CTF IR event type and functions.
-@sa ctfirevent
-
-@addtogroup ctfirevent
-@{
-*/
-
-/**
-@struct bt_event
-@brief A CTF IR event.
-@sa ctfirevent
-*/
struct bt_event;
struct bt_event_header_field;
-struct bt_clock;
struct bt_clock_value;
struct bt_event_class;
struct bt_field;
-struct bt_field_type;
-struct bt_stream_class;
struct bt_packet;
-/**
-@name Creation and parent access functions
-@{
-*/
-
-/**
-@brief Creates a default CTF IR event from the CTF IR event class
- \p event_class.
-
-\p event_class \em must have a parent
-\link ctfirstreamclass CTF IR stream class\endlink.
-
-On success, the four fields of the created event object are not set. You
-can set them with bt_event_set_header(),
-bt_event_set_stream_event_context(),
-bt_event_set_context(), and bt_event_set_payload().
-
-This function tries to resolve the needed
-\link ctfirfieldtypes CTF IR field type\endlink of the dynamic field
-types that are found anywhere in the context or payload field
-types of \p event_class and in the root field types of the
-parent stream class of \p event_class. If any automatic resolving fails,
-this function fails. This means that, if any dynamic field type need
-a field type which should be found in the trace packet header root
-field type, and if the parent stream class of \p event_class was not
-added to a \link ctfirtraceclass CTF IR trace class\endlink yet
-with bt_trace_add_stream_class(), then this function fails.
-
-@param[in] event_class CTF IR event class to use to create the
- CTF IR event.
-@returns Created event object, or \c NULL on error.
-
-@prenotnull{event_class}
-@pre \p event_class has a parent stream class.
-@postsuccessrefcountret1
-*/
extern struct bt_event_class *bt_event_borrow_class(struct bt_event *event);
-/**
-@brief Returns the parent CTF IR event class of the CTF IR event
- \p event.
-
-This function returns a reference to the event class which was used to
-create the event object in the first place with bt_event_create().
-
-@param[in] event Event of which to get the parent event class.
-@returns Parent event class of \p event,
- or \c NULL on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_event_class *bt_event_get_class(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_class(event));
-}
-
extern struct bt_packet *bt_event_borrow_packet(struct bt_event *event);
-/**
-@brief Returns the CTF IR packet associated to the CTF IR event
- \p event.
-
-This function returns a reference to the event class which was set to
-\p event in the first place with bt_event_set_packet().
-
-@param[in] event Event of which to get the associated packet.
-@returns Packet associated to \p event,
- or \c NULL if no packet is associated to
- \p event or on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-
-@sa bt_event_set_packet(): Associates a given event to a given
- packet.
-*/
-static inline
-struct bt_packet *bt_event_get_packet(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_packet(event));
-}
-
extern struct bt_stream *bt_event_borrow_stream(struct bt_event *event);
-/**
-@brief Returns the parent CTF IR stream associated to the CTF IR event
- \p event.
-
-@param[in] event Event of which to get the parent stream.
-@returns Parent stream of \p event, or \c NULL on error.
-
-@prenotnull{event}
-@postrefcountsame{event}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_stream *bt_event_get_stream(struct bt_event *event)
-{
- return bt_get(bt_event_borrow_stream(event));
-}
-
-/** @} */
-
-/**
-@name Contained fields functions
-@{
-*/
-
-extern struct bt_field *bt_event_borrow_header(struct bt_event *event);
+extern struct bt_field *bt_event_borrow_header_field(struct bt_event *event);
extern int bt_event_move_header(struct bt_event *event,
struct bt_event_header_field *header);
-extern struct bt_field *bt_event_borrow_stream_event_context(
+extern struct bt_field *bt_event_borrow_common_context_field(
struct bt_event *event);
-extern struct bt_field *bt_event_borrow_context(struct bt_event *event);
-
-extern struct bt_field *bt_event_borrow_payload(struct bt_event *event);
-
-/** @} */
-
-/**
-@name Clock value functions
-@{
-*/
-
-extern int bt_event_set_clock_value(struct bt_event *event,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default);
-
-extern struct bt_clock_value *bt_event_borrow_default_clock_value(
+extern struct bt_field *bt_event_borrow_specific_context_field(
struct bt_event *event);
-/** @} */
+extern struct bt_field *bt_event_borrow_payload_field(struct bt_event *event);
+
+extern int bt_event_set_default_clock_value(struct bt_event *event,
+ uint64_t value_cycles);
-/** @} */
+extern enum bt_clock_value_status bt_event_borrow_default_clock_value(
+ struct bt_event *event, struct bt_clock_value **clock_value);
#ifdef __cplusplus
}
* http://www.efficios.com/ctf
*/
-#include <babeltrace/common-internal.h>
#include <babeltrace/object-internal.h>
+#include <babeltrace/ctf-ir/field-path.h>
#include <babeltrace/assert-internal.h>
#include <glib.h>
struct bt_object base;
enum bt_scope root;
- /*
- * Array of integers (int) indicating the index in either
- * structures, variants, arrays, or sequences that make up
- * the path to a field type. -1 means the "current element
- * of an array or sequence type".
- */
+ /* Array of `uint64_t` (indexes) */
GArray *indexes;
};
BT_HIDDEN
struct bt_field_path *bt_field_path_create(void);
-BT_HIDDEN
-void bt_field_path_clear(struct bt_field_path *field_path);
-
-BT_HIDDEN
-struct bt_field_path *bt_field_path_copy(
- struct bt_field_path *path);
+static inline
+uint64_t bt_field_path_get_index_by_index_inline(
+ struct bt_field_path *field_path, uint64_t index)
+{
+ BT_ASSERT(field_path);
+ BT_ASSERT(index < field_path->indexes->len);
+ return g_array_index(field_path->indexes, uint64_t, index);
+}
#endif /* BABELTRACE_CTF_IR_FIELD_PATH_INTERNAL */
/*
* BabelTrace - CTF IR: Field path
*
- * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
extern "C" {
#endif
-struct bt_field_type;
-
-/**
-@defgroup ctfirfieldpath CTF IR field path
-@ingroup ctfir
-@brief CTF IR field path.
-
-@code
-#include <babeltrace/ctf-ir/field-path.h>
-@endcode
-
-A CTF IR <strong><em>field path</em></strong> represents an absolute
-path to a field in the hierarchy of a
-\link ctfirtraceclass CTF IR trace class\endlink, of a
-\link ctfirstreamclass CTF IR stream class\endlink, or of a
-\link ctfireventclass CTF IR event class\endlink.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-Sequence and variant \link ctfirfieldtypes CTF IR field types\endlink
-can return a field path to resp. their length field and tag field
-with resp. bt_field_type_sequence_get_length_field_path() and
-bt_field_type_variant_get_tag_field_path().
-
-A field path has a <em>root scope</em> which indicates from which of the
-six CTF scopes to begin. It also has a list of structure field <em>path
-indexes</em> which indicate the path to take to reach the destination
-field. A path index set to -1 means that you need to continue the lookup
-within the current element of an array or sequence field.
-
-As with any Babeltrace object, CTF IR field path objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-@file
-@brief CTF IR field path type and functions.
-@sa ctfirfieldpath
-
-@addtogroup ctfirfieldpath
-@{
-*/
-
-/**
-@struct bt_field_path
-@brief A CTF IR field path.
-@sa ctfirfieldpath
-*/
struct bt_field_path;
-/**
-@brief Returns the root scope of the CTF IR field path \p field_path.
+enum bt_scope {
+ BT_SCOPE_PACKET_HEADER,
+ BT_SCOPE_PACKET_CONTEXT,
+ BT_SCOPE_EVENT_HEADER,
+ BT_SCOPE_EVENT_COMMON_CONTEXT,
+ BT_SCOPE_EVENT_SPECIFIC_CONTEXT,
+ BT_SCOPE_EVENT_PAYLOAD,
+};
-@param[in] field_path Field path of which to get the root scope.
-@returns Root scope of \p field_path, or
- #BT_SCOPE_UNKNOWN on error.
-
-@prenotnull{field_path}
-@postrefcountsame{field_path}
-*/
extern enum bt_scope bt_field_path_get_root_scope(
- const struct bt_field_path *field_path);
-
-/**
-@brief Returns the number of path indexes contained in the CTF IR field
- path \p field_path.
-
-@param[in] field_path Field path of which to get the number of
- path indexes.
-@returns Number of path indexes contained in
- \p field_path, or a negative value on error.
-
-@prenotnull{field_path}
-@postrefcountsame{field_path}
-*/
-extern int64_t bt_field_path_get_index_count(
- const struct bt_field_path *field_path);
-
-/**
-@brief Returns the path index contained in the CTF IR field
- path \p field_path at index \p index.
-
-@param[in] field_path Field path of which to get the path index
- at index \p index.
-@param[in] index Index of path index to get.
-@returns Path index of \p field_path at index \p index,
- or \c INT_MIN on error.
+ struct bt_field_path *field_path);
-@prenotnull{field_path}
-@pre \p index is lesser than the number of path indexes contained in the
- field path \p field_path (see
- bt_field_path_get_index_count()).
-@postrefcountsame{field_path}
-*/
-extern int bt_field_path_get_index(
- const struct bt_field_path *field_path, uint64_t index);
+extern uint64_t bt_field_path_get_index_count(
+ struct bt_field_path *field_path);
-/** @} */
+extern uint64_t bt_field_path_get_index_by_index(
+ struct bt_field_path *field_path, uint64_t index);
#ifdef __cplusplus
}
#include <stdint.h>
#include <glib.h>
-#define BT_ASSERT_PRE_FT_HAS_ID(_ft, _type_id, _name) \
- BT_ASSERT_PRE(((struct bt_field_type *) (_ft))->id == (_type_id), \
- _name " has the wrong type ID: expected-type-id=%s, " \
- "%![ft-]+F", bt_common_field_type_id_string(_type_id), (_ft))
+#define BT_ASSERT_PRE_FT_IS_INT(_ft, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \
+ _name " is not an integer field type: %![ft-]+F", (_ft))
+
+#define BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(_ft, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \
+ _name " is not an unsigned integer field type: %![ft-]+F", (_ft))
+
+#define BT_ASSERT_PRE_FT_IS_ENUM(_ft, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \
+ _name " is not an enumeration field type: %![ft-]+F", (_ft))
+
+#define BT_ASSERT_PRE_FT_IS_ARRAY(_ft, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \
+ ((struct bt_field_type *) (_ft))->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \
+ _name " is not an array field type: %![ft-]+F", (_ft))
+
+#define BT_ASSERT_PRE_FT_HAS_ID(_ft, _id, _name) \
+ BT_ASSERT_PRE(((struct bt_field_type *) (_ft))->id == (_id), \
+ _name " has the wrong ID: expected-id=%s, " \
+ "%![ft-]+F", bt_common_field_type_id_string(_id), (_ft))
#define BT_ASSERT_PRE_FT_HOT(_ft, _name) \
- BT_ASSERT_PRE_HOT((_ft), (_name), ": %!+F", (_ft))
+ BT_ASSERT_PRE_HOT((struct bt_field_type *) (_ft), \
+ (_name), ": %!+F", (_ft))
-#define BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(_ft, _index) \
- (&g_array_index(((struct bt_field_type_structure *) (_ft))->fields, \
- struct bt_field_type_structure_field, (_index)))
+#define BT_FIELD_TYPE_NAMED_FT_AT_INDEX(_ft, _index) \
+ (&g_array_index(((struct bt_field_type_named_field_types_container *) (_ft))->named_fts, \
+ struct bt_named_field_type, (_index)))
-#define BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(_ft, _index) \
- (&g_array_index(((struct bt_field_type_variant *) (_ft))->choices, \
- struct bt_field_type_variant_choice, (_index)))
+#define BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(_ft, _index) \
+ (&g_array_index(((struct bt_field_type_enumeration *) (_ft))->mappings, \
+ struct bt_field_type_enumeration_mapping, (_index)))
+
+#define BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(_mapping, _index) \
+ (&g_array_index((_mapping)->ranges, \
+ struct bt_field_type_enumeration_mapping_range, (_index)))
struct bt_field;
struct bt_field_type;
-typedef void (*bt_field_type_method_freeze)(
- struct bt_field_type *);
-typedef int (*bt_field_type_method_validate)(
- struct bt_field_type *);
-typedef void (*bt_field_type_method_set_byte_order)(
- struct bt_field_type *, enum bt_byte_order);
-typedef struct bt_field_type *(*bt_field_type_method_copy)(
- struct bt_field_type *);
-typedef int (*bt_field_type_method_compare)(
- struct bt_field_type *,
- struct bt_field_type *);
-
-struct bt_field_type_methods {
- bt_field_type_method_freeze freeze;
- bt_field_type_method_validate validate;
- bt_field_type_method_set_byte_order set_byte_order;
- bt_field_type_method_copy copy;
- bt_field_type_method_compare compare;
-};
-
struct bt_field_type {
struct bt_object base;
enum bt_field_type_id id;
- unsigned int alignment;
-
- /* Virtual table */
- struct bt_field_type_methods *methods;
-
- /*
- * A type can't be modified once it is added to an event or after a
- * a field has been instanciated from it.
- */
- int frozen;
+ bool frozen;
/*
- * This flag indicates if the field type is valid. A valid
- * field type is _always_ frozen. All the nested field types of
- * a valid field type are also valid (and thus frozen).
+ * Only used in developer mode, this flag indicates whether or
+ * not this field type is part of a trace.
*/
- int valid;
+ bool part_of_trace;
};
struct bt_field_type_integer {
struct bt_field_type common;
- /* Owned by this */
- struct bt_clock_class *mapped_clock_class;
+ /*
+ * Value range of fields built from this integer field type:
+ * this is an equivalent integer size in bits. More formally,
+ * `range` is `n` in:
+ *
+ * Unsigned range: [0, 2^n - 1]
+ * Signed range: [-2^(n - 1), 2^(n - 1) - 1]
+ */
+ uint64_t range;
- enum bt_byte_order user_byte_order;
- bt_bool is_signed;
- unsigned int size;
- enum bt_integer_base base;
- enum bt_string_encoding encoding;
+ enum bt_field_type_integer_preferred_display_base base;
};
-struct enumeration_mapping {
+struct bt_field_type_enumeration_mapping_range {
union {
- uint64_t _unsigned;
- int64_t _signed;
- } range_start;
+ uint64_t u;
+ int64_t i;
+ } lower;
+
union {
- uint64_t _unsigned;
- int64_t _signed;
- } range_end;
- GQuark string;
+ uint64_t u;
+ int64_t i;
+ } upper;
};
-struct bt_field_type_enumeration {
- struct bt_field_type common;
-
- /* Owned by this */
- struct bt_field_type_integer *container_ft;
+struct bt_field_type_enumeration_mapping {
+ GString *label;
- /* Array of `struct enumeration_mapping *`, owned by this */
- GPtrArray *entries;
-
- /* Only set during validation */
- bt_bool has_overlapping_ranges;
+ /* Array of `struct bt_field_type_enumeration_mapping_range` */
+ GArray *ranges;
};
-enum bt_field_type_enumeration_mapping_iterator_type {
- ITERATOR_BY_NAME,
- ITERATOR_BY_SIGNED_VALUE,
- ITERATOR_BY_UNSIGNED_VALUE,
-};
+struct bt_field_type_enumeration {
+ struct bt_field_type_integer common;
-struct bt_field_type_enumeration_mapping_iterator {
- struct bt_object base;
+ /* Array of `struct bt_field_type_enumeration_mapping *` */
+ GArray *mappings;
- /* Owned by this */
- struct bt_field_type_enumeration *enumeration_ft;
+ /*
+ * This is an array of `const char *` which acts as a temporary
+ * (potentially growing) buffer for
+ * bt_field_type_unsigned_enumeration_get_mapping_labels_by_value()
+ * and
+ * bt_field_type_signed_enumeration_get_mapping_labels_by_value().
+ *
+ * The actual strings are owned by the mappings above.
+ */
+ GPtrArray *label_buf;
+};
- enum bt_field_type_enumeration_mapping_iterator_type type;
- int index;
- union {
- GQuark name_quark;
- int64_t signed_value;
- uint64_t unsigned_value;
- } u;
+struct bt_field_type_real {
+ struct bt_field_type common;
+ bool is_single_precision;
};
-struct bt_field_type_floating_point {
+struct bt_field_type_string {
struct bt_field_type common;
- enum bt_byte_order user_byte_order;
- unsigned int exp_dig;
- unsigned int mant_dig;
};
-struct bt_field_type_structure_field {
- GQuark name;
+/* A named field type is a (name, field type) pair */
+struct bt_named_field_type {
+ GString *name;
/* Owned by this */
- struct bt_field_type *type;
+ struct bt_field_type *ft;
};
-struct bt_field_type_structure {
+/*
+ * This is the base field type for a container of named field types.
+ * Structure and variant field types inherit this.
+ */
+struct bt_field_type_named_field_types_container {
struct bt_field_type common;
- GHashTable *field_name_to_index;
/*
- * Array of `struct bt_field_type_structure_field`,
- * owned by this
+ * Key: `const char *`, not owned by this (owned by named field
+ * type objects contained in `named_fts` below).
*/
- GArray *fields;
-};
+ GHashTable *name_to_index;
-struct bt_field_type_variant_choice_range {
- union {
- int64_t i;
- uint64_t u;
- } lower;
- union {
- int64_t i;
- uint64_t u;
- } upper;
+ /* Array of `struct bt_named_field_type` */
+ GArray *named_fts;
};
-struct bt_field_type_variant_choice {
- GQuark name;
-
- /* Owned by this */
- struct bt_field_type *type;
-
- /* Array of `struct bt_field_type_variant_choice_range` */
- GArray *ranges;
-};
-
-struct bt_field_type_variant {
- struct bt_field_type common;
- GString *tag_name;
- bool choices_up_to_date;
-
- /* Owned by this */
- struct bt_field_type_enumeration *tag_ft;
-
- /* Owned by this */
- struct bt_field_path *tag_field_path;
-
- GHashTable *choice_name_to_index;
-
- /*
- * Array of `struct bt_field_type_variant_choice`,
- * owned by this */
- GArray *choices;
+struct bt_field_type_structure {
+ struct bt_field_type_named_field_types_container common;
};
struct bt_field_type_array {
/* Owned by this */
struct bt_field_type *element_ft;
+};
- unsigned int length;
+struct bt_field_type_static_array {
+ struct bt_field_type_array common;
+ uint64_t length;
};
-struct bt_field_type_sequence {
- struct bt_field_type common;
+struct bt_field_type_dynamic_array {
+ struct bt_field_type_array common;
- /* Owned by this */
- struct bt_field_type *element_ft;
-
- GString *length_field_name;
+ /* Weak: never dereferenced, only use to find it elsewhere */
+ struct bt_field_type *length_ft;
/* Owned by this */
struct bt_field_path *length_field_path;
};
-struct bt_field_type_string {
- struct bt_field_type common;
- enum bt_string_encoding encoding;
-};
+struct bt_field_type_variant {
+ struct bt_field_type_named_field_types_container common;
+
+ /* Weak: never dereferenced, only use to find it elsewhere */
+ struct bt_field_type *selector_ft;
-typedef struct bt_field *(* bt_field_create_func)(
- struct bt_field_type *);
+ /* Owned by this */
+ struct bt_field_path *selector_field_path;
+};
-BT_ASSERT_FUNC
-static inline bool bt_field_type_has_known_id(
- struct bt_field_type *ft)
+static inline
+bool bt_field_type_has_known_id(struct bt_field_type *ft)
{
- return (int) ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
- (int) ft->id < BT_FIELD_TYPE_ID_NR;
+ return ft->id >= BT_FIELD_TYPE_ID_UNSIGNED_INTEGER &&
+ ft->id <= BT_FIELD_TYPE_ID_VARIANT;
}
BT_HIDDEN
-int bt_field_type_variant_update_choices(
- struct bt_field_type *ft);
-
-BT_HIDDEN
-void bt_field_type_freeze(struct bt_field_type *ft);
-
-BT_HIDDEN
-int bt_field_type_validate(struct bt_field_type *ft);
-
-BT_HIDDEN
-int bt_field_type_sequence_set_length_field_path(
- struct bt_field_type *ft, struct bt_field_path *path);
-
-BT_HIDDEN
-int bt_field_type_variant_set_tag_field_path(
- struct bt_field_type *ft,
- struct bt_field_path *path);
-
-BT_HIDDEN
-int bt_field_type_variant_set_tag_field_type(
- struct bt_field_type *ft,
- struct bt_field_type *tag_ft);
+void _bt_field_type_freeze(struct bt_field_type *field_type);
-BT_HIDDEN
-int64_t bt_field_type_get_field_count(struct bt_field_type *ft);
-
-BT_HIDDEN
-struct bt_field_type *bt_field_type_borrow_field_at_index(
- struct bt_field_type *ft, int index);
-
-BT_HIDDEN
-int bt_field_type_get_field_index(struct bt_field_type *ft,
- const char *name);
+#ifdef BT_DEV_MODE
+# define bt_field_type_freeze _bt_field_type_freeze
+#else
+# define bt_field_type_freeze(_ft)
+#endif
+/*
+ * This function recursively marks `field_type` and its children as
+ * being part of a trace. This is used to validate that all field types
+ * are used at a single location within trace objects even if they are
+ * shared objects for other purposes.
+ */
BT_HIDDEN
-int bt_field_type_validate_single_clock_class(
- struct bt_field_type *ft,
- struct bt_clock_class **expected_clock_class);
+void _bt_field_type_make_part_of_trace(struct bt_field_type *field_type);
-BT_HIDDEN
-int64_t bt_field_type_variant_find_choice_index(
- struct bt_field_type *ft, uint64_t uval,
- bool is_signed);
+#ifdef BT_DEV_MODE
+# define bt_field_type_make_part_of_trace _bt_field_type_make_part_of_trace
+#else
+# define bt_field_type_make_part_of_trace(_ft) ((void) _ft)
+#endif
#endif /* BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H */
extern "C" {
#endif
-/**
-@defgroup ctfirfieldtypes CTF IR field types
-@ingroup ctfir
-@brief CTF IR field types.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>field type</em></strong> is a field type that you
-can use to create concrete @fields.
-
-You can create a @field object from a CTF IR field type object
-with bt_field_create().
-
-In the CTF IR hierarchy, you can set the root field types of three
-objects:
-
-- \ref ctfirtraceclass
- - Trace packet header field type: bt_trace_set_packet_header_field_type().
-- \ref ctfirstreamclass
- - Stream packet context field type:
- bt_stream_class_set_packet_context_field_type().
- - Stream event header field type:
- bt_stream_class_set_event_header_field_type().
- - Stream event context field type:
- bt_stream_class_set_event_context_field_type().
-- \ref ctfireventclass
- - Event context field type: bt_event_class_set_context_field_type().
- - Event payload field type: bt_event_class_set_payload_field_type().
-
-As of Babeltrace \btversion, those six previous "root" field types
-\em must be @structft objects.
-
-If, at any level within a given root field type, you add a @seqft or a
-@varft, you do not need to specify its associated length
-or tag field type: the length or tag string is enough for the Babeltrace
-system to resolve the needed field type depending on where this
-dynamic field type is located within the whole hierarchy. It is
-guaranteed that this automatic resolving is performed for all the field
-types contained in a given
-\link ctfirstreamclass CTF IR stream class\endlink (and in its
-children \link ctfireventclass CTF IR event classes\endlink) once you
-add it to a \link ctfirtraceclass CTF IR trace class\endlink with
-bt_trace_add_stream_class(). Once a stream class is the child of
-a trace class, this automatic resolving is performed for the field
-types of an event class when you add it with
-bt_stream_class_add_event_class(). If the system cannot find a path
-to a field in the hierarchy for a dynamic field type, the adding
-function fails.
-
-The standard CTF field types are:
-
-<table>
- <tr>
- <th>Type ID
- <th>CTF IR field type
- <th>CTF IR field which you can create from this field type
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_INTEGER
- <td>\ref ctfirintfieldtype
- <td>\ref ctfirintfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_FLOAT
- <td>\ref ctfirfloatfieldtype
- <td>\ref ctfirfloatfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_ENUM
- <td>\ref ctfirenumfieldtype
- <td>\ref ctfirenumfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_STRING
- <td>\ref ctfirstringfieldtype
- <td>\ref ctfirstringfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_STRUCT
- <td>\ref ctfirstructfieldtype
- <td>\ref ctfirstructfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_ARRAY
- <td>\ref ctfirarrayfieldtype
- <td>\ref ctfirarrayfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_SEQUENCE
- <td>\ref ctfirseqfieldtype
- <td>\ref ctfirseqfield
- </tr>
- <tr>
- <td>#BT_FIELD_TYPE_ID_VARIANT
- <td>\ref ctfirvarfieldtype
- <td>\ref ctfirvarfield
- </tr>
-</table>
-
-Each field type has its own <strong>type ID</strong> (see
-#bt_field_type_id). You get the type ID of a field type object
-with bt_field_type_get_type_id().
-
-You can get a deep copy of a field type with bt_field_type_copy().
-This function resets, in the field type copy, the resolved field type
-of the dynamic field types. The automatic resolving can be done again
-when you eventually call bt_event_create(),
-bt_stream_class_add_event_class(), or
-bt_trace_add_stream_class().
-
-You \em must always use bt_field_type_compare() to compare two
-field types. Since some parts of the Babeltrace system can copy field
-types behind the scenes, you \em cannot rely on a simple field type
-pointer comparison.
-
-As with any Babeltrace object, CTF IR field type objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-The following functions can \em freeze field type objects:
-
-- bt_field_create() freezes its field type parameter.
-- bt_stream_class_add_event_class(), if its
- \link ctfirstreamclass CTF IR stream class\endlink parameter has a
- \link ctfirtraceclass CTF IR trace class\endlink parent, freezes
- the root field types of its
- \link ctfireventclass CTF IR event class\endlink parameter.
-- bt_trace_add_stream_class() freezes the root field types of the
- whole trace class hierarchy (trace class, children stream classes,
- and their children event classes).
-- bt_writer_create_stream() freezes the root field types of the
- whole CTF writer's trace class hierarchy.
-- bt_event_create() freezes the root field types of its event class
- parameter and of ther parent stream class of this event class.
-
-You cannot modify a frozen field type object: it is considered
-immutable, except for \link refs reference counting\endlink.
-
-@sa ctfirfields
-@sa \ref ctfirfieldtypesexamples "Examples"
-
-@file
-@brief CTF IR field types type and functions.
-@sa ctfirfieldtypes
-
-@addtogroup ctfirfieldtypes
-@{
-*/
-
-/**
-@struct bt_field_type
-@brief A CTF IR field type.
-@sa ctfirfieldtypes
-*/
struct bt_field_type;
-struct bt_event_class;
-struct bt_event;
-struct bt_field;
struct bt_field_path;
-struct bt_field_type_enumeration_mapping_iterator;
-
-/**
-@brief CTF scope.
-*/
-enum bt_scope {
- /// Unknown, used for errors.
- BT_SCOPE_UNKNOWN = -1,
-
- /// Trace packet header.
- BT_SCOPE_TRACE_PACKET_HEADER = 1,
-
- /// Stream packet context.
- BT_SCOPE_STREAM_PACKET_CONTEXT = 2,
+struct bt_field_type_signed_enumeration_mapping_ranges;
+struct bt_field_type_unsigned_enumeration_mapping_ranges;
- /// Stream event header.
- BT_SCOPE_STREAM_EVENT_HEADER = 3,
+typedef const char * const *bt_field_type_enumeration_mapping_label_array;
- /// Stream event context.
- BT_SCOPE_STREAM_EVENT_CONTEXT = 4,
-
- /// Event context.
- BT_SCOPE_EVENT_CONTEXT = 5,
-
- /// Event payload.
- BT_SCOPE_EVENT_PAYLOAD = 6,
-
- /// @cond DOCUMENT
- BT_SCOPE_ENV = 0,
- BT_SCOPE_EVENT_FIELDS = 6,
- /// @endcond
-};
-
-/**
-@name Type information
-@{
-*/
-
-/**
-@brief Type ID of a @ft.
-*/
enum bt_field_type_id {
- /// Unknown, used for errors.
- BT_FIELD_TYPE_ID_UNKNOWN = -1,
-
- /// \ref ctfirintfieldtype
- BT_FIELD_TYPE_ID_INTEGER = 0,
-
- /// \ref ctfirfloatfieldtype
- BT_FIELD_TYPE_ID_FLOAT = 1,
-
- /// \ref ctfirenumfieldtype
- BT_FIELD_TYPE_ID_ENUM = 2,
-
- /// \ref ctfirstringfieldtype
- BT_FIELD_TYPE_ID_STRING = 3,
-
- /// \ref ctfirstructfieldtype
- BT_FIELD_TYPE_ID_STRUCT = 4,
-
- /// \ref ctfirarrayfieldtype
- BT_FIELD_TYPE_ID_ARRAY = 6,
-
- /// \ref ctfirseqfieldtype
- BT_FIELD_TYPE_ID_SEQUENCE = 7,
-
- /// \ref ctfirvarfieldtype
- BT_FIELD_TYPE_ID_VARIANT = 5,
-
- /// Number of enumeration entries.
- BT_FIELD_TYPE_ID_NR = 8,
+ BT_FIELD_TYPE_ID_UNSIGNED_INTEGER,
+ BT_FIELD_TYPE_ID_SIGNED_INTEGER,
+ BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION,
+ BT_FIELD_TYPE_ID_SIGNED_ENUMERATION,
+ BT_FIELD_TYPE_ID_REAL,
+ BT_FIELD_TYPE_ID_STRING,
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ BT_FIELD_TYPE_ID_STATIC_ARRAY,
+ BT_FIELD_TYPE_ID_DYNAMIC_ARRAY,
+ BT_FIELD_TYPE_ID_VARIANT,
};
-/**
-@brief Returns the type ID of the @ft \p field_type.
-
-@param[in] field_type Field type of which to get the type ID.
-@returns Type ID of \p field_type,
- or #BT_FIELD_TYPE_ID_UNKNOWN on error.
-
-@prenotnull{field_type}
-@postrefcountsame{field_type}
+enum bt_field_type_integer_preferred_display_base {
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY,
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL,
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL,
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL,
+};
-@sa #bt_field_type_id: CTF IR field type ID.
-@sa bt_field_type_is_integer(): Returns whether or not a given
- field type is a @intft.
-@sa bt_field_type_is_floating_point(): Returns whether or not a
- given field type is a @floatft.
-@sa bt_field_type_is_enumeration(): Returns whether or not a given
- field type is a @enumft.
-@sa bt_field_type_is_string(): Returns whether or not a given
- field type is a @stringft.
-@sa bt_field_type_is_structure(): Returns whether or not a given
- field type is a @structft.
-@sa bt_field_type_is_array(): Returns whether or not a given
- field type is a @arrayft.
-@sa bt_field_type_is_sequence(): Returns whether or not a given
- field type is a @seqft.
-@sa bt_field_type_is_variant(): Returns whether or not a given
- field type is a @varft.
-*/
extern enum bt_field_type_id bt_field_type_get_type_id(
struct bt_field_type *field_type);
-/**
-@brief Returns whether or not the @ft \p field_type is a @intft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is an integer field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@prenotnull{field_type}
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_integer(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) ==
- BT_FIELD_TYPE_ID_INTEGER;
-}
+extern struct bt_field_type *bt_field_type_unsigned_integer_create(void);
-/**
-@brief Returns whether or not the @ft \p field_type is a @floatft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is a floating point
- #BT_FALSE field type,
- or 0 otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_floating_point(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) == BT_FIELD_TYPE_ID_FLOAT;
-}
-
-/**
-@brief Returns whether or not the @ft \p field_type is a @enumft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is an enumeration field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_enumeration(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) == BT_FIELD_TYPE_ID_ENUM;
-}
-
-/**
-@brief Returns whether or not the @ft \p field_type is a @stringft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is a string field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_string(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) == BT_FIELD_TYPE_ID_STRING;
-}
+extern struct bt_field_type *bt_field_type_signed_integer_create(void);
-/**
-@brief Returns whether or not the @ft \p field_type is a @structft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is a structure field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_structure(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) == BT_FIELD_TYPE_ID_STRUCT;
-}
-
-/**
-@brief Returns whether or not the @ft \p field_type is a @arrayft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is an array field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_array(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) == BT_FIELD_TYPE_ID_ARRAY;
-}
-
-/**
-@brief Returns whether or not the @ft \p field_type is a @seqft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is a sequence field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_sequence(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) ==
- BT_FIELD_TYPE_ID_SEQUENCE;
-}
-
-/**
-@brief Returns whether or not the @ft \p field_type is a @varft.
-
-@param[in] field_type Field type to check (can be \c NULL).
-@returns #BT_TRUE if \p field_type is a variant field type,
- or #BT_FALSE otherwise (including if \p field_type is
- \c NULL).
-
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_type_id(): Returns the type ID of a given
- field type.
-*/
-static inline
-bt_bool bt_field_type_is_variant(struct bt_field_type *field_type)
-{
- return bt_field_type_get_type_id(field_type) ==
- BT_FIELD_TYPE_ID_VARIANT;
-}
-
-/** @} */
-
-/**
-@name Common properties types and functions
-@{
-*/
-
-/**
-@brief <a href="https://en.wikipedia.org/wiki/Endianness">Byte order</a>
- of a @ft.
-*/
-enum bt_byte_order {
- /// Unknown, used for errors.
- BT_BYTE_ORDER_UNKNOWN = -1,
-
- /*
- * Note that native, in the context of the CTF specification, is defined
- * as "the byte order described in the trace" and does not mean that the
- * host's endianness will be used.
- */
- /// Native (default) byte order.
- BT_BYTE_ORDER_NATIVE = 0,
-
- /**
- Unspecified byte order; the initial native byte order of a
- \link ctfirtraceclass CTF IR trace class\endlink.
- */
- BT_BYTE_ORDER_UNSPECIFIED,
-
- /// Little-endian.
- BT_BYTE_ORDER_LITTLE_ENDIAN,
-
- /// Big-endian.
- BT_BYTE_ORDER_BIG_ENDIAN,
-
- /// Network byte order (big-endian).
- BT_BYTE_ORDER_NETWORK,
-};
-
-/**
-@brief String encoding of a @ft.
-*/
-enum bt_string_encoding {
- /// Unknown, used for errors.
- BT_STRING_ENCODING_UNKNOWN = -1,
-
- /// No encoding.
- BT_STRING_ENCODING_NONE,
-
- /// <a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a>.
- BT_STRING_ENCODING_UTF8,
-
- /// <a href="https://en.wikipedia.org/wiki/ASCII">ASCII</a>.
- BT_STRING_ENCODING_ASCII,
-};
-
-/**
-@brief Returns the alignment of the @fields described by
- the @ft \p field_type.
-
-@param[in] field_type Field type which describes the
- fields of which to get the alignment.
-@returns Alignment of the fields described by
- \p field_type, or a negative value on error.
-
-@prenotnull{field_type}
-@postrefcountsame{field_type}
-
-@sa bt_field_type_set_alignment(): Sets the alignment
- of the fields described by a given field type.
-*/
-extern int bt_field_type_get_alignment(
+extern uint64_t bt_field_type_integer_get_field_value_range(
struct bt_field_type *field_type);
-/**
-@brief Sets the alignment of the @fields described by the
- @ft \p field_type to \p alignment.
-
-\p alignment \em must be greater than 0 and a power of two.
-
-@param[in] field_type Field type which describes the fields of
- which to set the alignment.
-@param[in] alignment Alignment of the fields described by
- \p field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{field_type}
-@prehot{field_type}
-@pre \p alignment is greater than 0 and a power of two.
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_alignment(): Returns the alignment of the
- fields described by a given field type.
-*/
-extern int bt_field_type_set_alignment(struct bt_field_type *field_type,
- unsigned int alignment);
-
-/**
-@brief Returns the byte order of the @fields described by
- the @ft \p field_type.
-
-You can only call this function if \p field_type is a @intft, a
-@floatft, or a @enumft.
-
-@param[in] field_type Field type which describes the
- fields of which to get the byte order.
-@returns Byte order of the fields described by
- \p field_type, or #BT_BYTE_ORDER_UNKNOWN on
- error.
+extern int bt_field_type_integer_set_field_value_range(
+ struct bt_field_type *field_type, uint64_t size);
-@prenotnull{field_type}
-@pre \p field_type is a @intft, a @floatft, or a @enumft.
-@postrefcountsame{field_type}
-
-@sa bt_field_type_set_byte_order(): Sets the byte order
- of the fields described by a given field type.
-*/
-extern enum bt_byte_order bt_field_type_get_byte_order(
+extern enum bt_field_type_integer_preferred_display_base
+bt_field_type_integer_get_preferred_display_base(
struct bt_field_type *field_type);
-/**
-@brief Sets the byte order of the @fields described by the
- @ft \p field_type to \p byte_order.
-
-If \p field_type is a compound field type, this function also
-recursively sets the byte order of its children to \p byte_order.
-
-@param[in] field_type Field type which describes the fields of
- which to set the byte order.
-@param[in] byte_order Alignment of the fields described by
- \p field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{field_type}
-@prehot{field_type}
-@pre \p byte_order is #BT_BYTE_ORDER_NATIVE,
- #BT_BYTE_ORDER_LITTLE_ENDIAN, #BT_BYTE_ORDER_BIG_ENDIAN,
- or #BT_BYTE_ORDER_NETWORK.
-@postrefcountsame{field_type}
-
-@sa bt_field_type_get_byte_order(): Returns the byte order of the
- fields described by a given field type.
-*/
-extern int bt_field_type_set_byte_order(
+extern int bt_field_type_integer_set_preferred_display_base(
struct bt_field_type *field_type,
- enum bt_byte_order byte_order);
-
-/** @} */
-
-/**
-@name Utility functions
-@{
-*/
-
-/**
-@brief Returns whether or not the @ft \p field_type_a
- is equivalent to the field type \p field_type_b.
-
-You \em must use this function to compare two field types: it is not
-safe to compare two pointer values directly, because, for internal
-reasons, some parts of the Babeltrace system can copy user field types
-and discard the original ones.
-
-@param[in] field_type_a Field type to compare to \p field_type_b.
-@param[in] field_type_b Field type to compare to \p field_type_a.
-@returns 0 if \p field_type_a is equivalent to
- \p field_type_b, 1 if they are not equivalent,
- or a negative value on error.
-
-@prenotnull{field_type_a}
-@prenotnull{field_type_b}
-@postrefcountsame{field_type_a}
-@postrefcountsame{field_type_b}
-*/
-extern int bt_field_type_compare(struct bt_field_type *field_type_a,
- struct bt_field_type *field_type_b);
-
-/**
-@brief Creates a \em deep copy of the @ft \p field_type.
-
-You can copy a frozen field type: the resulting copy is
-<em>not frozen</em>.
-
-This function resets the tag field type of a copied @varft. The
-automatic field resolving which some functions of the API perform
-can set it again when the returned field type is used (learn more
-in the detailed description of this module).
+ enum bt_field_type_integer_preferred_display_base base);
-@param[in] field_type Field type to copy.
-@returns Deep copy of \p field_type on success,
- or \c NULL on error.
+extern struct bt_field_type *bt_field_type_real_create(void);
-@prenotnull{field_type}
-@postrefcountsame{field_type}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned field type is not frozen.
-*/
-extern struct bt_field_type *bt_field_type_copy(
+extern bt_bool bt_field_type_real_is_single_precision(
struct bt_field_type *field_type);
-/** @} */
-
-/** @} */
-
-/**
-@defgroup ctfirintfieldtype CTF IR integer field type
-@ingroup ctfirfieldtypes
-@brief CTF IR integer field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>integer field type</em></strong> is a field type that
-you can use to create concrete @intfield objects.
-
-You can create an integer field type
-with bt_field_type_integer_create().
-
-An integer field type has the following properties:
-
-<table>
- <tr>
- <th>Property
- <th>Value at creation
- <th>Getter
- <th>Setter
- </tr>
- <tr>
- <td>\b Alignment (bits) of the described integer fields
- <td>1
- <td>bt_field_type_get_alignment()
- <td>bt_field_type_set_alignment()
- </tr>
- <tr>
- <td><strong>Byte order</strong> of the described integer fields
- <td>#BT_BYTE_ORDER_NATIVE
- <td>bt_field_type_get_byte_order()
- <td>bt_field_type_set_byte_order()
- </tr>
- <tr>
- <td><strong>Storage size</strong> (bits) of the described
- integer fields
- <td>Specified at creation
- <td>bt_field_type_integer_get_size()
- <td>bt_field_type_integer_set_size()
- </tr>
- <tr>
- <td><strong>Signedness</strong> of the described integer fields
- <td>Unsigned
- <td>bt_field_type_integer_is_signed()
- <td>bt_field_type_integer_set_is_signed()
- </tr>
- <tr>
- <td><strong>Preferred display base</strong> of the described
- integer fields
- <td>#BT_INTEGER_BASE_DECIMAL
- <td>bt_field_type_integer_get_base()
- <td>bt_field_type_integer_set_base()
- </tr>
- <tr>
- <td>\b Encoding of the described integer fields
- <td>#BT_STRING_ENCODING_NONE
- <td>bt_field_type_integer_get_encoding()
- <td>bt_field_type_integer_set_encoding()
- </tr>
- <tr>
- <td><strong>Mapped
- \link ctfirclockclass CTF IR clock class\endlink</strong>
- <td>None
- <td>bt_field_type_integer_get_mapped_clock_class()
- <td>bt_field_type_integer_set_mapped_clock_class()
- </tr>
-</table>
-
-@sa ctfirintfield
-@sa ctfirfieldtypes
-@sa \ref ctfirfieldtypesexamples_intfieldtype "Examples"
-
-@addtogroup ctfirintfieldtype
-@{
-*/
-
-/**
-@brief Preferred display base (radix) of a @intft.
-*/
-enum bt_integer_base {
- /// Unknown, used for errors.
- BT_INTEGER_BASE_UNKNOWN = -1,
-
- /// Unspecified by the tracer.
- BT_INTEGER_BASE_UNSPECIFIED = 0,
-
- /// Binary.
- BT_INTEGER_BASE_BINARY = 2,
-
- /// Octal.
- BT_INTEGER_BASE_OCTAL = 8,
-
- /// Decimal.
- BT_INTEGER_BASE_DECIMAL = 10,
-
- /// Hexadecimal.
- BT_INTEGER_BASE_HEXADECIMAL = 16,
-};
-
-/**
-@brief Creates a default @intft with \p size bits as the storage size
- of the @intfields it describes.
-
-You can change the storage size of the integer fields described by
-the created integer field type later with
-bt_field_type_integer_set_size().
-
-@param[in] size Storage size (bits) of the described integer fields.
-@returns Created integer field type, or \c NULL on error.
-
-@pre \p size is greater than 0 and lesser than or equal to 64.
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_integer_create(
- unsigned int size);
-
-/**
-@brief Returns the storage size, in bits, of the @intfields
- described by the @intft \p int_field_type.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to get the
- storage size.
-@returns Storage size (bits) of the integer
- fields described by \p int_field_type,
- or a negative value on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_set_size(): Sets the storage size of the
- integer fields described by a given integer field type.
-*/
-extern int bt_field_type_integer_get_size(
- struct bt_field_type *int_field_type);
-
-/**
-@brief Sets the storage size, in bits, of the @intfields described by
- the @intft \p int_field_type.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to set the
- storage size.
-@param[in] size Storage size (bits) of the integer fields
- described by \p int_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@prehot{int_field_type}
-@pre \p size is greater than 0 and lesser than or equal to 64.
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_get_size(): Returns the storage size of
- the integer fields described by a given integer field type.
-*/
-extern int bt_field_type_integer_set_size(
- struct bt_field_type *int_field_type, unsigned int size);
-
-/**
-@brief Returns whether or not the @intfields described by the @intft
- \p int_field_type are signed.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to get the
- signedness.
-@returns #BT_TRUE if the integer fields described by
- \p int_field_type are signed, #BT_FALSE if they
- are unsigned.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_set_is_signed(): Sets the signedness of the
- integer fields described by a given integer field type.
-*/
-extern bt_bool bt_field_type_integer_is_signed(
- struct bt_field_type *int_field_type);
-
-/**
-@brief Sets whether or not the @intfields described by
- the @intft \p int_field_type are signed.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to set the
- signedness.
-@param[in] is_signed Signedness of the integer fields
- described by \p int_field_type; #BT_FALSE means
- \em unsigned, #BT_TRUE means \em signed.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@prehot{int_field_type}
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_is_signed(): Returns the signedness of
- the integer fields described by a given integer field type.
-*/
-extern int bt_field_type_integer_set_is_signed(
- struct bt_field_type *int_field_type, bt_bool is_signed);
-
-/**
-@brief Returns the preferred display base (radix) of the @intfields
- described by the @intft \p int_field_type.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to get the
- preferred display base.
-@returns Preferred display base of the integer
- fields described by \p int_field_type,
- #BT_INTEGER_BASE_UNSPECIFIED if
- not specified, or
- #BT_INTEGER_BASE_UNKNOWN on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_set_base(): Sets the preferred display
- base of the integer fields described by a given integer field
- type.
-*/
-extern enum bt_integer_base bt_field_type_integer_get_base(
- struct bt_field_type *int_field_type);
-
-/**
-@brief Sets the preferred display base (radix) of the @intfields
- described by the @intft \p int_field_type to \p base.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to set the
- preferred display base.
-@param[in] base Preferred display base of the integer
- fields described by \p int_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@prehot{int_field_type}
-@pre \p base is #BT_INTEGER_BASE_UNSPECIFIED,
- #BT_INTEGER_BASE_BINARY, #BT_INTEGER_BASE_OCTAL,
- #BT_INTEGER_BASE_DECIMAL, or #BT_INTEGER_BASE_HEXADECIMAL.
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_get_base(): Returns the preferred display
- base of the integer fields described by a given
- integer field type.
-*/
-extern int bt_field_type_integer_set_base(
- struct bt_field_type *int_field_type,
- enum bt_integer_base base);
-
-/**
-@brief Returns the encoding of the @intfields described by
- the @intft \p int_field_type.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to get the
- encoding.
-@returns Encoding of the integer
- fields described by \p int_field_type,
- or #BT_STRING_ENCODING_UNKNOWN on
- error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_set_encoding(): Sets the encoding
- of the integer fields described by a given integer field type.
-*/
-extern enum bt_string_encoding bt_field_type_integer_get_encoding(
- struct bt_field_type *int_field_type);
-
-/**
-@brief Sets the encoding of the @intfields described by the @intft
- \p int_field_type to \p encoding.
-
-You can use this property, in CTF IR, to create "text" @arrayfts or
-@seqfts. A text array field type is array field type with an unsigned,
-8-bit integer field type having an encoding as its element field type.
-
-@param[in] int_field_type Integer field type which describes the
- integer fields of which to set the
- encoding.
-@param[in] encoding Encoding of the integer
- fields described by \p int_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@prehot{int_field_type}
-@pre \p encoding is #BT_STRING_ENCODING_NONE,
- #BT_STRING_ENCODING_ASCII, or
- #BT_STRING_ENCODING_UTF8.
-@postrefcountsame{int_field_type}
-
-@sa bt_field_type_integer_get_encoding(): Returns the encoding of
- the integer fields described by a given integer field type.
-*/
-extern int bt_field_type_integer_set_encoding(
- struct bt_field_type *int_field_type,
- enum bt_string_encoding encoding);
-
-extern struct bt_clock_class *bt_field_type_integer_borrow_mapped_clock_class(
- struct bt_field_type *int_field_type);
-
-/**
-@brief Returns the \link ctfirclockclass CTF IR clock class\endlink
- mapped to the @intft \p int_field_type.
-
-The mapped clock class, if any, indicates the class of the clock which
-an @intfield described by \p int_field_type should sample or update.
-This mapped clock class is only indicative.
-
-@param[in] int_field_type Integer field type of which to get the
- mapped clock class.
-@returns Mapped clock class of \p int_field_type,
- or \c NULL if there's no mapped clock
- class or on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postrefcountsame{int_field_type}
-@postsuccessrefcountretinc
-
-@sa bt_field_type_integer_set_mapped_clock_class(): Sets the mapped
- clock class of a given integer field type.
-*/
-static inline
-struct bt_clock_class *bt_field_type_integer_get_mapped_clock_class(
- struct bt_field_type *int_field_type)
-{
- return bt_get(bt_field_type_integer_borrow_mapped_clock_class(
- int_field_type));
-}
-
-/**
-@brief Sets the \link ctfirclockclass CTF IR clock class\endlink mapped
- to the @intft \p int_field_type to \p clock_class.
-
-The mapped clock class, if any, indicates the class of the clock which
-an integer field described by \p int_field_type should sample or update.
-This mapped clock class is only indicative.
-
-@param[in] int_field_type Integer field type of which to set the
- mapped clock class.
-@param[in] clock_class Mapped clock class of \p int_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{int_field_type}
-@prenotnull{clock_class}
-@preisintft{int_field_type}
-@prehot{int_field_type}
-@postrefcountsame{int_field_type}
-@postsuccessrefcountinc{clock_class}
-
-@sa bt_field_type_integer_get_mapped_clock_class(): Returns the mapped
- clock class of a given integer field type.
-*/
-extern int bt_field_type_integer_set_mapped_clock_class(
- struct bt_field_type *int_field_type,
- struct bt_clock_class *clock_class);
-
-/** @} */
-
-/**
-@defgroup ctfirfloatfieldtype CTF IR floating point number field type
-@ingroup ctfirfieldtypes
-@brief CTF IR floating point number field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>floating point number field type</em></strong> is
-a field type that you can use to create concrete @floatfields.
-
-You can create a floating point number field type
-with bt_field_type_floating_point_create().
-
-A floating point number field type has the following properties:
-
-<table>
- <tr>
- <th>Property
- <th>Value at creation
- <th>Getter
- <th>Setter
- </tr>
- <tr>
- <td>\b Alignment (bits) of the described floating point
- number fields
- <td>1
- <td>bt_field_type_get_alignment()
- <td>bt_field_type_set_alignment()
- </tr>
- <tr>
- <td><strong>Byte order</strong> of the described floating point
- number fields
- <td>#BT_BYTE_ORDER_NATIVE
- <td>bt_field_type_get_byte_order()
- <td>bt_field_type_set_byte_order()
- </tr>
- <tr>
- <td><strong>Exponent storage size</strong> (bits) of the described
- floating point number fields
- <td>8
- <td>bt_field_type_floating_point_get_exponent_digits()
- <td>bt_field_type_floating_point_set_exponent_digits()
- </tr>
- <tr>
- <td><strong>Mantissa and sign storage size</strong> (bits) of the
- described floating point number fields
- <td>24 (23-bit mantissa, 1-bit sign)
- <td>bt_field_type_floating_point_get_mantissa_digits()
- <td>bt_field_type_floating_point_set_mantissa_digits()
- </tr>
-</table>
-
-@sa ctfirfloatfield
-@sa ctfirfieldtypes
-@sa \ref ctfirfieldtypesexamples_floatfieldtype "Examples"
-
-@addtogroup ctfirfloatfieldtype
-@{
-*/
-
-/**
-@brief Creates a default @floatft.
-
-@returns Created floating point number field type,
- or \c NULL on error.
-
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_floating_point_create(void);
-
-/**
-@brief Returns the exponent storage size of the @floatfields
- described by the @floatft \p float_field_type.
-
-@param[in] float_field_type Floating point number field type which
- describes the floating point number
- fields of which to get the exponent
- storage size.
-@returns Exponent storage size of the
- floating point number fields
- described by \p float_field_type,
- or a negative value on error.
-
-@prenotnull{float_field_type}
-@preisfloatft{float_field_type}
-@postrefcountsame{float_field_type}
-
-@sa bt_field_type_floating_point_set_exponent_digits(): Sets the
- exponent storage size of the floating point number fields
- described by a given floating point number field type.
-*/
-extern int bt_field_type_floating_point_get_exponent_digits(
- struct bt_field_type *float_field_type);
-
-/**
-@brief Sets the exponent storage size of the @floatfields described by
- the @floatft \p float_field_type to \p exponent_size.
-
-As of Babeltrace \btversion, \p exponent_size can only be 8 or 11.
-
-@param[in] float_field_type Floating point number field type which
- describes the floating point number
- fields of which to set the exponent
- storage size.
-@param[in] exponent_size Exponent storage size of the floating
- point number fields described by \p
- float_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{float_field_type}
-@preisfloatft{float_field_type}
-@prehot{float_field_type}
-@pre \p exponent_size is 8 or 11.
-@postrefcountsame{float_field_type}
-
-@sa bt_field_type_floating_point_get_exponent_digits(): Returns the
- exponent storage size of the floating point number fields
- described by a given floating point number field type.
-*/
-extern int bt_field_type_floating_point_set_exponent_digits(
- struct bt_field_type *float_field_type,
- unsigned int exponent_size);
-
-/**
-@brief Returns the mantissa and sign storage size of the @floatfields
- described by the @floatft \p float_field_type.
-
-On success, the returned value is the sum of the mantissa \em and
-sign storage sizes.
-
-@param[in] float_field_type Floating point number field type which
- describes the floating point number
- fields of which to get the mantissa and
- sign storage size.
-@returns Mantissa and sign storage size of the
- floating point number fields
- described by \p float_field_type,
- or a negative value on error.
-
-@prenotnull{float_field_type}
-@preisfloatft{float_field_type}
-@postrefcountsame{float_field_type}
-
-@sa bt_field_type_floating_point_set_mantissa_digits(): Sets the
- mantissa and size storage size of the floating point number
- fields described by a given floating point number field type.
-*/
-extern int bt_field_type_floating_point_get_mantissa_digits(
- struct bt_field_type *float_field_type);
-
-/**
-@brief Sets the mantissa and sign storage size of the @floatfields
- described by the @floatft \p float_field_type to \p
- mantissa_sign_size.
-
-As of Babeltrace \btversion, \p mantissa_sign_size can only be 24 or 53.
-
-@param[in] float_field_type Floating point number field type which
- describes the floating point number
- fields of which to set the mantissa and
- sign storage size.
-@param[in] mantissa_sign_size Mantissa and sign storage size of the
- floating point number fields described
- by \p float_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{float_field_type}
-@preisfloatft{float_field_type}
-@prehot{float_field_type}
-@pre \p mantissa_sign_size is 24 or 53.
-@postrefcountsame{float_field_type}
-
-@sa bt_field_type_floating_point_get_mantissa_digits(): Returns the
- mantissa and sign storage size of the floating point number
- fields described by a given floating point number field type.
-*/
-extern int bt_field_type_floating_point_set_mantissa_digits(
- struct bt_field_type *float_field_type,
- unsigned int mantissa_sign_size);
-
-/** @} */
-
-/**
-@defgroup ctfirenumfieldtype CTF IR enumeration field type
-@ingroup ctfirfieldtypes
-@brief CTF IR enumeration field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>enumeration field type</em></strong> is
-a field type that you can use to create concrete @enumfields.
-
-You can create an enumeration field type with
-bt_field_type_enumeration_create(). This function needs a @intft
-which represents the storage field type of the created enumeration field
-type. In other words, an enumeration field type wraps an integer field
-type and adds label-value mappings to it.
-
-An enumeration mapping has:
-
-- A <strong>name</strong>.
-- A <strong>range of values</strong> given by a beginning and an ending
- value, both included in the range.
-
-You can add a mapping to an enumeration field type with
-bt_field_type_enumeration_signed_add_mapping() or
-bt_field_type_enumeration_unsigned_add_mapping(), depending on the
-signedness of the wrapped @intft.
-
-You can find mappings by name or by value with the following find
-operations:
-
-- bt_field_type_enumeration_find_mappings_by_name(): Finds the
- mappings with a given name.
-- bt_field_type_enumeration_unsigned_find_mappings_by_value():
- Finds the mappings which contain a given unsigned value in their
- range.
-- bt_field_type_enumeration_signed_find_mappings_by_value():
- Finds the mappings which contain a given signed value in their range.
-
-Those functions return a @enumftiter on the result set of the find
-operation.
-
-Many mappings can share the same name, and the ranges of a given
-enumeration field type are allowed to overlap. For example,
-this is a valid set of mappings:
-
-@verbatim
-APPLE -> [ 3, 19]
-BANANA -> [-15, 1]
-CHERRY -> [ 25, 34]
-APPLE -> [ 55, 55]
-@endverbatim
-
-The following set of mappings is also valid:
-
-@verbatim
-APPLE -> [ 3, 19]
-BANANA -> [-15, 1]
-CHERRY -> [ 25, 34]
-APPLE -> [ 30, 55]
-@endverbatim
-
-Here, the range of the second \c APPLE mapping overlaps the range of
-the \c CHERRY mapping.
-
-@sa ctfirenumftmappingiter
-@sa ctfirenumfield
-@sa ctfirfieldtypes
-
-@addtogroup ctfirenumfieldtype
-@{
-*/
-
-/**
-@brief Creates a default @enumft wrapping the @intft \p int_field_type.
-
-@param[in] int_field_type Integer field type wrapped by the
- created enumeration field type.
-@returns Created enumeration field type,
- or \c NULL on error.
-
-@prenotnull{int_field_type}
-@preisintft{int_field_type}
-@postsuccessrefcountinc{int_field_type}
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_enumeration_create(
- struct bt_field_type *int_field_type);
-
-extern
-struct bt_field_type *bt_field_type_enumeration_borrow_container_field_type(
- struct bt_field_type *enum_field_type);
-
-/**
-@brief Returns the @intft wrapped by the @enumft \p enum_field_type.
-
-@param[in] enum_field_type Enumeration field type of which to get
- the wrapped integer field type.
-@returns Integer field type wrapped by
- \p enum_field_type, or \c NULL on
- error.
-
-@prenotnull{enum_field_type}
-@preisenumft{enum_field_type}
-@postrefcountsame{enum_field_type}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field_type *bt_field_type_enumeration_get_container_field_type(
- struct bt_field_type *enum_field_type)
-{
- return bt_get(bt_field_type_enumeration_borrow_container_field_type(
- enum_field_type));
-}
-
-/**
-@brief Returns the number of mappings contained in the
- @enumft \p enum_field_type.
-
-@param[in] enum_field_type Enumeration field type of which to get
- the number of contained mappings.
-@returns Number of mappings contained in
- \p enum_field_type, or a negative
- value on error.
-
-@prenotnull{enum_field_type}
-@preisenumft{enum_field_type}
-@postrefcountsame{enum_field_type}
-*/
-extern int64_t bt_field_type_enumeration_get_mapping_count(
- struct bt_field_type *enum_field_type);
-
-/**
-@brief Returns the signed mapping of the @enumft
- \p enum_field_type at index \p index.
-
-The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be \b signed
-to use this function.
-
-On success, \p enum_field_type remains the sole owner of \p *name.
-
-@param[in] enum_field_type Enumeration field type of which to get
- the mapping at index \p index.
-@param[in] index Index of the mapping to get from
- \p enum_field_type.
-@param[out] name Returned name of the mapping at index
- \p index.
-@param[out] range_begin Returned beginning of the range
- (included) of the mapping at index \p
- index.
-@param[out] range_end Returned end of the range (included) of
- the mapping at index \p index.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{enum_field_type}
-@prenotnull{name}
-@prenotnull{range_begin}
-@prenotnull{range_end}
-@preisenumft{enum_field_type}
-@pre The wrapped @intft of \p enum_field_type is signed.
-@pre \p index is lesser than the number of mappings contained in the
- enumeration field type \p enum_field_type (see
- bt_field_type_enumeration_get_mapping_count()).
-@postrefcountsame{enum_field_type}
-
-@sa bt_field_type_enumeration_unsigned_get_mapping_by_index(): Returns the
- unsigned mapping contained by a given enumeration field type
- at a given index.
-*/
-extern int bt_field_type_enumeration_signed_get_mapping_by_index(
- struct bt_field_type *enum_field_type, uint64_t index,
- const char **name, int64_t *range_begin, int64_t *range_end);
-
-/**
-@brief Returns the unsigned mapping of the @enumft
- \p enum_field_type at index \p index.
-
-The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be
-\b unsigned to use this function.
-
-On success, \p enum_field_type remains the sole owner of \p *name.
-
-@param[in] enum_field_type Enumeration field type of which to get
- the mapping at index \p index.
-@param[in] index Index of the mapping to get from
- \p enum_field_type.
-@param[out] name Returned name of the mapping at index
- \p index.
-@param[out] range_begin Returned beginning of the range
- (included) of the mapping at index \p
- index.
-@param[out] range_end Returned end of the range (included) of
- the mapping at index \p index.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{enum_field_type}
-@prenotnull{name}
-@prenotnull{range_begin}
-@prenotnull{range_end}
-@preisenumft{enum_field_type}
-@pre The wrapped @intft of \p enum_field_type is unsigned.
-@pre \p index is lesser than the number of mappings contained in the
- enumeration field type \p enum_field_type (see
- bt_field_type_enumeration_get_mapping_count()).
-@postrefcountsame{enum_field_type}
-
-@sa bt_field_type_enumeration_signed_get_mapping_by_index(): Returns the
- signed mapping contained by a given enumeration field type
- at a given index.
-*/
-extern int bt_field_type_enumeration_unsigned_get_mapping_by_index(
- struct bt_field_type *enum_field_type, uint64_t index,
- const char **name, uint64_t *range_begin,
- uint64_t *range_end);
-
-/**
-@brief Finds the mappings of the @enumft \p enum_field_type which
- are named \p name.
-
-This function returns an iterator on the result set of this find
-operation. See \ref ctfirenumftmappingiter for more details.
-
-@param[in] enum_field_type Enumeration field type of which to find
- the mappings named \p name.
-@param[in] name Name of the mappings to find in
- \p enum_field_type.
-@returns @enumftiter on the set of mappings named
- \p name in \p enum_field_type, or
- \c NULL if no mappings were found or
- on error.
-
-@prenotnull{enum_field_type}
-@prenotnull{name}
-@preisenumft{enum_field_type}
-@postrefcountsame{enum_field_type}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned @enumftiter can iterate
- on at least one mapping.
-
-@sa bt_field_type_enumeration_signed_find_mappings_by_value(): Finds
- the mappings of a given enumeration field type which contain
- a given signed value in their range.
-@sa bt_field_type_enumeration_unsigned_find_mappings_by_value(): Finds
- the mappings of a given enumeration field type which contain
- a given unsigned value in their range.
-*/
-extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_name(
- struct bt_field_type *enum_field_type,
- const char *name);
-
-/**
-@brief Finds the mappings of the @enumft \p enum_field_type which
- contain the signed value \p value in their range.
-
-This function returns an iterator on the result set of this find
-operation. See \ref ctfirenumftmappingiter for more details.
-
-@param[in] enum_field_type Enumeration field type of which to find
- the mappings which contain \p value.
-@param[in] value Value to find in the ranges of the
- mappings of \p enum_field_type.
-@returns @enumftiter on the set of mappings of
- \p enum_field_type which contain
- \p value in their range, or \c NULL if
- no mappings were found or on error.
-
-@prenotnull{enum_field_type}
-@preisenumft{enum_field_type}
-@postrefcountsame{enum_field_type}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned @enumftiter can iterate
- on at least one mapping.
-
-@sa bt_field_type_enumeration_find_mappings_by_name(): Finds the
- mappings of a given enumeration field type which have a given
- name.
-@sa bt_field_type_enumeration_unsigned_find_mappings_by_value(): Finds
- the mappings of a given enumeration field type which contain
- a given unsigned value in their range.
-*/
-extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_signed_find_mappings_by_value(
- struct bt_field_type *enum_field_type,
- int64_t value);
-
-/**
-@brief Finds the mappings of the @enumft \p enum_field_type which
- contain the unsigned value \p value in their range.
-
-This function returns an iterator on the result set of this find
-operation. See \ref ctfirenumftmappingiter for more details.
-
-@param[in] enum_field_type Enumeration field type of which to find
- the mappings which contain \p value.
-@param[in] value Value to find in the ranges of the
- mappings of \p enum_field_type.
-@returns @enumftiter on the set of mappings of
- \p enum_field_type which contain
- \p value in their range, or \c NULL
- if no mappings were found or
- on error.
-
-@prenotnull{enum_field_type}
-@preisenumft{enum_field_type}
-@postrefcountsame{enum_field_type}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned @enumftiter can iterate
- on at least one mapping.
-
-@sa bt_field_type_enumeration_find_mappings_by_name(): Finds the
- mappings of a given enumeration field type which have a given
- name.
-@sa bt_field_type_enumeration_signed_find_mappings_by_value(): Finds
- the mappings of a given enumeration field type which contain
- a given unsigned value in their range.
-*/
-extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_unsigned_find_mappings_by_value(
- struct bt_field_type *enum_field_type,
- uint64_t value);
-
-/**
-@brief Adds a mapping to the @enumft \p enum_field_type which maps the
- name \p name to the signed range \p range_begin (included) to
- \p range_end (included).
-
-Make \p range_begin and \p range_end the same value to add a mapping
-to a single value.
-
-The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be
-\b signed to use this function.
-
-A mapping in \p enum_field_type can exist with the name \p name.
-
-@param[in] enum_field_type Enumeration field type to which to add
- a mapping.
-@param[in] name Name of the mapping to add (copied
- on success).
-@param[in] range_begin Beginning of the range of the mapping
- (included).
-@param[in] range_end End of the range of the mapping
- (included).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{enum_field_type}
-@prenotnull{name}
-@prehot{enum_field_type}
-@preisenumft{enum_field_type}
-@pre The wrapped @intft of \p enum_field_type is signed.
-@pre \p range_end is greater than or equal to \p range_begin.
-@postrefcountsame{enum_field_type}
-
-@sa bt_field_type_enumeration_unsigned_add_mapping(): Adds an
- unsigned mapping to a given enumeration field type.
-*/
-extern int bt_field_type_enumeration_signed_add_mapping(
- struct bt_field_type *enum_field_type, const char *name,
- int64_t range_begin, int64_t range_end);
-
-/**
-@brief Adds a mapping to the @enumft \p enum_field_type which maps
- the name \p name to the unsigned
- range \p range_begin (included) to \p range_end (included).
-
-Make \p range_begin and \p range_end the same value to add a mapping
-to a single value.
-
-The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be
-\b unsigned to use this function.
-
-A mapping in \p enum_field_type can exist with the name \p name.
-
-@param[in] enum_field_type Enumeration field type to which to add
- a mapping.
-@param[in] name Name of the mapping to add (copied
- on success).
-@param[in] range_begin Beginning of the range of the mapping
- (included).
-@param[in] range_end End of the range of the mapping
- (included).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{enum_field_type}
-@prenotnull{name}
-@prehot{enum_field_type}
-@preisenumft{enum_field_type}
-@pre The wrapped @intft of \p enum_field_type is unsigned.
-@pre \p range_end is greater than or equal to \p range_begin.
-@postrefcountsame{enum_field_type}
-
-@sa bt_field_type_enumeration_signed_add_mapping(): Adds a signed
- mapping to a given enumeration field type.
-*/
-extern int bt_field_type_enumeration_unsigned_add_mapping(
- struct bt_field_type *enum_field_type, const char *name,
- uint64_t range_begin, uint64_t range_end);
-
-/** @} */
-
-/**
-@defgroup ctfirenumftmappingiter CTF IR enumeration field type mapping iterator
-@ingroup ctfirenumfieldtype
-@brief CTF IR enumeration field type mapping iterator.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>enumeration field type mapping
-iterator</em></strong> is an iterator on @enumft mappings.
-
-You can get an enumeration mapping iterator from one of the following
-functions:
-
-- Find operations of an @enumft object:
- - bt_field_type_enumeration_find_mappings_by_name(): Finds the
- mappings with a given name.
- - bt_field_type_enumeration_unsigned_find_mappings_by_value():
- Finds the mappings which contain a given unsigned value in their
- range.
- - bt_field_type_enumeration_signed_find_mappings_by_value():
- Finds the mappings which contain a given signed value in their range.
-- bt_field_enumeration_get_mappings(): Finds the mappings in the
- @enumft of an @enumfield containing its current integral value in
- their range.
-
-Those functions guarantee that the returned iterator can iterate on
-at least one mapping. Otherwise, they return \c NULL.
-
-You can get the name and the range of a mapping iterator's current
-mapping with
-bt_field_type_enumeration_mapping_iterator_signed_get()
-or
-bt_field_type_enumeration_mapping_iterator_unsigned_get(),
-depending on the signedness of the @intft wrapped by the
-@enumft. If you only need the name of the current mapping, you can
-use any of the two functions and set the \p range_begin and \p range_end
-parameters to \c NULL.
-
-You can advance an enumeration field type mapping iterator to the next
-mapping with
-bt_field_type_enumeration_mapping_iterator_next(). This
-function returns a negative value when you reach the end of the
-result set.
-
-As with any Babeltrace object, CTF IR enumeration field type mapping
-iterator objects have <a
-href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-@sa ctfirenumfieldtype
-
-@addtogroup ctfirenumftmappingiter
-@{
-*/
-
-/**
-@struct bt_field_type_enumeration_mapping_iterator
-@brief A CTF IR enumeration field type mapping iterator.
-@sa ctfirenumftmappingiter
-*/
-
-/**
-@brief Returns the name and the range of the current (signed) mapping
- of the @enumftiter \p iter.
-
-If one of \p range_begin or \p range_end is not \c NULL, the @intft
-wrapped by the @enumft from which \p iter was obtained, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be
-\b signed to use this function. Otherwise, if you only need to get the
-name of the current mapping, set \p range_begin and \p range_end to
-\c NULL.
-
-On success, if \p name is not \c NULL, \p *name remains valid as long
-as \p iter exists and
-bt_field_type_enumeration_mapping_iterator_next() is
-\em not called on \p iter.
-
-@param[in] iter Enumeration field type mapping iterator
- of which to get the range of the current
- mapping.
-@param[out] name Returned name of the current mapping of
- \p iter (can be \c NULL to ignore).
-@param[out] range_begin Returned beginning of the range
- (included) of the current mapping of
- \p iter (can be \c NULL to ignore).
-@param[out] range_end Returned end of the range
- (included) of the current mapping of
- \p iter (can be \c NULL to ignore).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{iter}
-@postrefcountsame{iter}
-
-@sa bt_field_type_enumeration_mapping_iterator_unsigned_get():
- Returns the name and the unsigned range of the current mapping
- of a given enumeration field type mapping iterator.
-*/
-extern int bt_field_type_enumeration_mapping_iterator_signed_get(
- struct bt_field_type_enumeration_mapping_iterator *iter,
- const char **name, int64_t *range_begin, int64_t *range_end);
-
-/**
-@brief Returns the name and the range of the current (unsigned) mapping
- of the @enumftiter \p iter.
-
-If one of \p range_begin or \p range_end is not \c NULL, the @intft
-wrapped by the @enumft from which \p iter was obtained, as returned by
-bt_field_type_enumeration_get_container_field_type(), must be
-\b unsigned to use this function. Otherwise, if you only need to get the
-name of the current mapping, set \p range_begin and \p range_end to
-\c NULL.
-
-On success, if \p name is not \c NULL, \p *name remains valid as long
-as \p iter exists and
-bt_field_type_enumeration_mapping_iterator_next() is
-\em not called on \p iter.
-
-@param[in] iter Enumeration field type mapping iterator
- of which to get the range of the current
- mapping.
-@param[out] name Returned name of the current mapping of
- \p iter (can be \c NULL to ignore).
-@param[out] range_begin Returned beginning of the range
- (included) of the current mapping of
- \p iter (can be \c NULL to ignore).
-@param[out] range_end Returned end of the range
- (included) of the current mapping of
- \p iter (can be \c NULL to ignore).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{iter}
-@postrefcountsame{iter}
-
-@sa
- bt_field_type_enumeration_mapping_iterator_signed_get():
- Returns the name and the signed range of the current mapping of
- a given enumeration field type mapping iterator.
-*/
-extern int bt_field_type_enumeration_mapping_iterator_unsigned_get(
- struct bt_field_type_enumeration_mapping_iterator *iter,
- const char **name, uint64_t *range_begin, uint64_t *range_end);
+extern int bt_field_type_real_set_is_single_precision(
+ struct bt_field_type *field_type,
+ bt_bool is_single_precision);
-/**
-@brief Advances the @enumftiter \p iter to the next mapping.
+extern struct bt_field_type *bt_field_type_unsigned_enumeration_create(void);
-@param[in] iter Enumeration field type mapping iterator to
- advance.
-@returns 0 on success, or a negative value on error or
- when you reach the end of the set.
+extern struct bt_field_type *bt_field_type_signed_enumeration_create(void);
-@prenotnull{iter}
-@postrefcountsame{iter}
-*/
-extern int bt_field_type_enumeration_mapping_iterator_next(
- struct bt_field_type_enumeration_mapping_iterator *iter);
+extern uint64_t bt_field_type_enumeration_get_mapping_count(
+ struct bt_field_type *field_type);
-/** @} */
+extern void bt_field_type_unsigned_enumeration_borrow_mapping_by_index(
+ struct bt_field_type *field_type, uint64_t index,
+ const char **label,
+ struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges);
-/**
-@defgroup ctfirstringfieldtype CTF IR string field type
-@ingroup ctfirfieldtypes
-@brief CTF IR string field type.
+extern void bt_field_type_signed_enumeration_borrow_mapping_by_index(
+ struct bt_field_type *field_type, uint64_t index,
+ const char **label,
+ struct bt_field_type_signed_enumeration_mapping_ranges **ranges);
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
+extern uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges);
-A CTF IR <strong><em>string field type</em></strong> is a field type that
-you can use to create concrete @stringfields.
+extern uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count(
+ struct bt_field_type_signed_enumeration_mapping_ranges *ranges);
-You can create a string field type
-with bt_field_type_string_create().
+extern void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges,
+ uint64_t index, uint64_t *lower, uint64_t *upper);
-A string field type has only one property: the \b encoding of its
-described @stringfields. By default, the encoding of the string fields
-described by a string field type is #BT_STRING_ENCODING_UTF8. You
-can set the encoding of the string fields described by a string field
-type with bt_field_type_string_set_encoding().
+extern void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges,
+ uint64_t index, int64_t *lower, int64_t *upper);
-@sa ctfirstringfield
-@sa ctfirfieldtypes
+extern int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value(
+ struct bt_field_type *field_type, uint64_t value,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count);
-@addtogroup ctfirstringfieldtype
-@{
-*/
+extern int bt_field_type_signed_enumeration_get_mapping_labels_by_value(
+ struct bt_field_type *field_type, int64_t value,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count);
-/**
-@brief Creates a default @stringft.
+extern int bt_field_type_unsigned_enumeration_map_range(
+ struct bt_field_type *field_type, const char *label,
+ uint64_t range_lower, uint64_t range_upper);
-@returns Created string field type, or \c NULL on error.
+extern int bt_field_type_signed_enumeration_map_range(
+ struct bt_field_type *field_type, const char *label,
+ int64_t range_lower, int64_t range_upper);
-@postsuccessrefcountret1
-*/
extern struct bt_field_type *bt_field_type_string_create(void);
-/**
-@brief Returns the encoding of the @stringfields described by
- the @stringft \p string_field_type.
-
-@param[in] string_field_type String field type which describes the
- string fields of which to get the
- encoding.
-@returns Encoding of the string
- fields described by \p string_field_type,
- or #BT_STRING_ENCODING_UNKNOWN on
- error.
-
-@prenotnull{string_field_type}
-@preisstringft{string_field_type}
-@postrefcountsame{string_field_type}
-
-@sa bt_field_type_string_set_encoding(): Sets the encoding
- of the string fields described by a given string field type.
-*/
-extern enum bt_string_encoding bt_field_type_string_get_encoding(
- struct bt_field_type *string_field_type);
-
-/**
-@brief Sets the encoding of the @stringfields described by the
- @stringft \p string_field_type to \p encoding.
-
-@param[in] string_field_type String field type which describes the
- string fields of which to set the
- encoding.
-@param[in] encoding Encoding of the string fields described
- by \p string_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{string_field_type}
-@preisstringft{string_field_type}
-@prehot{string_field_type}
-@pre \p encoding is #BT_STRING_ENCODING_ASCII or
- #BT_STRING_ENCODING_UTF8.
-@postrefcountsame{string_field_type}
-
-@sa bt_field_type_string_get_encoding(): Returns the encoding of
- the string fields described by a given string field type.
-*/
-extern int bt_field_type_string_set_encoding(
- struct bt_field_type *string_field_type,
- enum bt_string_encoding encoding);
-
-/** @} */
-
-/**
-@defgroup ctfirstructfieldtype CTF IR structure field type
-@ingroup ctfirfieldtypes
-@brief CTF IR structure field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>structure field type</em></strong> is
-a field type that you can use to create concrete @structfields.
-
-You can create a structure field type
-with bt_field_type_structure_create(). This function creates
-an empty structure field type, with no fields.
-
-You can add a field to a structure field type with
-bt_field_type_structure_add_field(). Two fields in a structure
-field type cannot have the same name.
-
-You can set the \em minimum alignment of the structure fields described
-by a structure field type with the common
-bt_field_type_set_alignment() function. The \em effective alignment
-of the structure fields described by a structure field type, as per
-<a href="http://diamon.org/ctf/">CTF</a>, is the \em maximum value amongst
-the effective alignments of all its fields. Note that the effective
-alignment of @varfields is always 1.
-
-You can set the byte order of <em>all the contained fields</em>,
-recursively, of a structure field type with the common
-bt_field_type_set_byte_order() function.
-
-@sa ctfirstructfield
-@sa ctfirfieldtypes
-
-@addtogroup ctfirstructfieldtype
-@{
-*/
-
-/**
-@brief Creates a default, empty @structft.
-
-@returns Created structure field type,
- or \c NULL on error.
-
-@postsuccessrefcountret1
-*/
extern struct bt_field_type *bt_field_type_structure_create(void);
-/**
-@brief Returns the number of fields contained in the
- @structft \p struct_field_type.
-
-@param[in] struct_field_type Structure field type of which to get
- the number of contained fields.
-@returns Number of fields contained in
- \p struct_field_type, or a negative
- value on error.
-
-@prenotnull{struct_field_type}
-@preisstructft{struct_field_type}
-@postrefcountsame{struct_field_type}
-*/
-extern int64_t bt_field_type_structure_get_field_count(
- struct bt_field_type *struct_field_type);
-
-extern int bt_field_type_structure_borrow_field_by_index(
- struct bt_field_type *struct_field_type,
- const char **field_name, struct bt_field_type **field_type,
- uint64_t index);
-
-/**
-@brief Returns the field of the @structft \p struct_field_type
- at index \p index.
-
-On success, the field's type is placed in \p *field_type if
-\p field_type is not \c NULL. The field's name is placed in
-\p *field_name if \p field_name is not \c NULL.
-\p struct_field_type remains the sole owner of \p *field_name.
-
-@param[in] struct_field_type Structure field type of which to get
- the field at index \p index.
-@param[out] field_name Returned name of the field at index
- \p index (can be \c NULL).
-@param[out] field_type Returned field type of the field
- at index \p index (can be \c NULL).
-Â@param[in] index Index of the field to get from
- \p struct_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{struct_field_type}
-@preisstructft{struct_field_type}
-@pre \p index is lesser than the number of fields contained in the
- structure field type \p struct_field_type (see
- bt_field_type_structure_get_field_count()).
-@postrefcountsame{struct_field_type}
-@post <strong>On success</strong>, the returned field's type is placed
- in \p *field_type and its reference count is incremented.
-
-@sa bt_field_type_structure_get_field_type_by_name(): Finds a
- structure field type's field by name.
-*/
-static inline
-int bt_field_type_structure_get_field_by_index(
- struct bt_field_type *struct_field_type,
- const char **field_name, struct bt_field_type **field_type,
- uint64_t index)
-{
- int ret = bt_field_type_structure_borrow_field_by_index(
- struct_field_type, field_name, field_type, index);
-
- if (ret == 0 && field_type) {
- bt_get(*field_type);
- }
+extern uint64_t bt_field_type_structure_get_member_count(
+ struct bt_field_type *field_type);
- return ret;
-}
+extern void bt_field_type_structure_borrow_member_by_index(
+ struct bt_field_type *struct_field_type, uint64_t index,
+ const char **name, struct bt_field_type **field_type);
extern
-struct bt_field_type *bt_field_type_structure_borrow_field_type_by_name(
- struct bt_field_type *struct_field_type,
- const char *field_name);
-
-/**
-@brief Returns the type of the field named \p field_name found in
- the @structft \p struct_field_type.
-
-@param[in] struct_field_type Structure field type of which to get
- a field's type.
-@param[in] field_name Name of the field to find.
-@returns Type of the field named \p field_name in
- \p struct_field_type, or
- \c NULL on error.
-
-@prenotnull{struct_field_type}
-@prenotnull{field_name}
-@preisstructft{struct_field_type}
-@postrefcountsame{struct_field_type}
-@postsuccessrefcountretinc
-
-@sa bt_field_type_structure_get_field_by_index(): Finds a
- structure field type's field by index.
-*/
-static inline
-struct bt_field_type *bt_field_type_structure_get_field_type_by_name(
- struct bt_field_type *struct_field_type,
- const char *field_name)
-{
- return bt_get(bt_field_type_structure_borrow_field_type_by_name(
- struct_field_type, field_name));
-}
-
-/**
-@brief Adds a field named \p field_name with the @ft
- \p field_type to the @structft \p struct_field_type.
-
-On success, \p field_type becomes the child of \p struct_field_type.
-
-This function adds the new field after the current last field of
-\p struct_field_type (append mode).
+struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name(
+ struct bt_field_type *field_type, const char *name);
-You \em cannot add a field named \p field_name if there's already a
-field named \p field_name in \p struct_field_type.
-
-@param[in] struct_field_type Structure field type to which to add
- a new field.
-@param[in] field_type Field type of the field to add to
- \p struct_field_type.
-@param[in] field_name Name of the field to add to
- \p struct_field_type
- (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{struct_field_type}
-@prenotnull{field_type}
-@prenotnull{field_name}
-@preisstructft{struct_field_type}
-@pre \p field_type is not and does not contain \p struct_field_type,
- recursively, as a field's type.
-@prehot{struct_field_type}
-@postrefcountsame{struct_field_type}
-@postsuccessrefcountinc{field_type}
-*/
-extern int bt_field_type_structure_add_field(
- struct bt_field_type *struct_field_type,
- struct bt_field_type *field_type,
- const char *field_name);
-
-/** @} */
-
-/**
-@defgroup ctfirarrayfieldtype CTF IR array field type
-@ingroup ctfirfieldtypes
-@brief CTF IR array field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>array field type</em></strong> is a field type that
-you can use to create concrete @arrayfields.
-
-You can create an array field type
-with bt_field_type_array_create(). This function needs
-the @ft of the fields contained by the array fields described by the
-array field type to create.
-
-@sa ctfirarrayfield
-@sa ctfirfieldtypes
-
-@addtogroup ctfirarrayfieldtype
-@{
-*/
-
-/**
-@brief Creates a default @arrayft with
- \p element_field_type as the field type of the fields contained
- in its described @arrayfields of length \p length.
+extern int bt_field_type_structure_append_member(
+ struct bt_field_type *struct_field_type, const char *name,
+ struct bt_field_type *field_type);
-@param[in] element_field_type Field type of the fields contained in
- the array fields described by the
- created array field type.
-@param[in] length Length of the array fields described by
- the created array field type.
-@returns Created array field type, or
- \c NULL on error.
+extern struct bt_field_type *bt_field_type_static_array_create(
+ struct bt_field_type *elem_field_type,
+ uint64_t length);
-@prenotnull{element_field_type}
-@postsuccessrefcountinc{element_field_type}
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_array_create(
- struct bt_field_type *element_field_type,
- unsigned int length);
+extern struct bt_field_type *bt_field_type_dynamic_array_create(
+ struct bt_field_type *elem_field_type);
extern struct bt_field_type *bt_field_type_array_borrow_element_field_type(
- struct bt_field_type *array_field_type);
-
-/**
-@brief Returns the @ft of the @fields contained in
- the @arrayfields described by the @arrayft \p array_field_type.
-
-@param[in] array_field_type Array field type of which to get
- the type of the fields contained in its
- described array fields.
-@returns Type of the fields contained in the
- array fields described by
- \p array_field_type, or \c NULL
- on error.
-
-@prenotnull{array_field_type}
-@preisarrayft{array_field_type}
-@postrefcountsame{array_field_type}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field_type *bt_field_type_array_get_element_field_type(
- struct bt_field_type *array_field_type)
-{
- return bt_get(bt_field_type_array_borrow_element_field_type(
- array_field_type));
-}
-
-/**
-@brief Returns the number of @fields contained in the
- @arrayfields described by the @arrayft \p array_field_type.
-
-@param[in] array_field_type Array field type of which to get
- the number of fields contained in its
- described array fields.
-@returns Number of fields contained in the
- array fields described by
- \p array_field_type, or a negative value
- on error.
-
-@prenotnull{array_field_type}
-@preisarrayft{array_field_type}
-@postrefcountsame{array_field_type}
-*/
-extern int64_t bt_field_type_array_get_length(
- struct bt_field_type *array_field_type);
-
-/** @} */
-
-/**
-@defgroup ctfirseqfieldtype CTF IR sequence field type
-@ingroup ctfirfieldtypes
-@brief CTF IR sequence field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>sequence field type</em></strong> is
-a field type that you can use to create concrete @seqfields.
-
-You can create a sequence field type with
-bt_field_type_sequence_create(). This function needs the @ft
-of the fields contained by the sequence fields described by the created
-sequence field type. This function also needs the length name of the
-sequence field type to create. The length name is used to automatically
-resolve the length's field type. See \ref ctfirfieldtypes to learn more
-about the automatic resolving.
-
-@sa ctfirseqfield
-@sa ctfirfieldtypes
-
-@addtogroup ctfirseqfieldtype
-@{
-*/
-
-/**
-@brief Creates a default @seqft with \p element_field_type as the
- @ft of the @fields contained in its described @seqfields
- with the length name \p length_name.
-
-\p length_name can be an absolute or relative reference. See
-<a href="http://diamon.org/ctf/">CTF</a> for more details.
-
-@param[in] element_field_type Field type of the fields contained in
- the sequence fields described by the
- created sequence field type.
-@param[in] length_name Length name (copied on success).
-@returns Created array field type, or
- \c NULL on error.
-
-@prenotnull{element_field_type}
-@prenotnull{length_name}
-@postsuccessrefcountinc{element_field_type}
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_sequence_create(
- struct bt_field_type *element_field_type,
- const char *length_name);
-
-extern struct bt_field_type *bt_field_type_sequence_borrow_element_field_type(
- struct bt_field_type *sequence_field_type);
-
-/**
-@brief Returns the @ft of the @fields contained in the @seqft
- described by the @seqft \p sequence_field_type.
-
-@param[in] sequence_field_type Sequence field type of which to get
- the type of the fields contained in its
- described sequence fields.
-@returns Type of the fields contained in the
- sequence fields described by
- \p sequence_field_type, or \c NULL
- on error.
-
-@prenotnull{sequence_field_type}
-@preisseqft{sequence_field_type}
-@postrefcountsame{sequence_field_type}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field_type *bt_field_type_sequence_get_element_field_type(
- struct bt_field_type *sequence_field_type)
-{
- return bt_get(bt_field_type_sequence_borrow_element_field_type(
- sequence_field_type));
-}
-
-/**
-@brief Returns the length name of the @seqft \p sequence_field_type.
-
-On success, \p sequence_field_type remains the sole owner of
-the returned string.
-
-@param[in] sequence_field_type Sequence field type of which to get the
- length name.
-@returns Length name of \p sequence_field_type,
- or \c NULL on error.
-
-@prenotnull{sequence_field_type}
-@preisseqft{sequence_field_type}
-
-@sa bt_field_type_sequence_get_length_field_path(): Returns the
- length's CTF IR field path of a given sequence field type.
-*/
-extern const char *bt_field_type_sequence_get_length_field_name(
- struct bt_field_type *sequence_field_type);
-
-extern struct bt_field_path *bt_field_type_sequence_borrow_length_field_path(
- struct bt_field_type *sequence_field_type);
-
-/**
-@brief Returns the length's CTF IR field path of the @seqft
- \p sequence_field_type.
-
-The length's field path of a sequence field type is set when automatic
-resolving is performed (see \ref ctfirfieldtypes).
-
-@param[in] sequence_field_type Sequence field type of which to get the
- length's field path.
-@returns Length's field path of
- \p sequence_field_type, or
- \c NULL if the length's field path is
- not set yet is not set or on error.
-
-@prenotnull{sequence_field_type}
-@preisseqft{sequence_field_type}
-@postsuccessrefcountretinc
-
-@sa bt_field_type_sequence_get_length_field_name(): Returns the
- length's name of a given sequence field type.
-*/
-static inline
-struct bt_field_path *bt_field_type_sequence_get_length_field_path(
- struct bt_field_type *sequence_field_type)
-{
- return bt_get(bt_field_type_sequence_borrow_length_field_path(
- sequence_field_type));
-}
-
-/** @} */
-
-/**
-@defgroup ctfirvarfieldtype CTF IR variant field type
-@ingroup ctfirfieldtypes
-@brief CTF IR variant field type.
-
-@code
-#include <babeltrace/ctf-ir/field-types.h>
-@endcode
-
-A CTF IR <strong><em>variant field type</em></strong> is
-a field type that you can use to create concrete @varfields.
-
-You can create a variant field type with
-bt_field_type_variant_create(). This function expects you to pass
-both the tag's @enumft and the tag name of the variant field type to
-create. The tag's field type is optional, as the Babeltrace system can
-automatically resolve it using the tag name. You can leave the tag name
-to \c NULL initially, and set it later with
-bt_field_type_variant_set_tag_name(). The tag name must be set when
-the variant field type is frozen. See \ref ctfirfieldtypes to learn more
-about the automatic resolving and the conditions under which a field
-type can be frozen.
-
-You can add a field to a variant field type with
-bt_field_type_variant_add_field(). All the field names of a
-variant field type \em must exist as mapping names in its tag's @enumft.
-
-The effective alignment of the @varfields described by a
-variant field type is always 1, but the individual fields of a
-@varfield can have custom alignments.
-
-You can set the byte order of <em>all the contained fields</em>,
-recursively, of a variant field type with the common
-bt_field_type_set_byte_order() function.
-
-@sa ctfirvarfield
-@sa ctfirfieldtypes
-
-@addtogroup ctfirvarfieldtype
-@{
-*/
-
-/**
-@brief Creates a default, empty @varft with the tag's @enumft
- \p tag_field_type and the tag name \p tag_name.
-
-\p tag_field_type can be \c NULL; the tag's field type can be
-automatically resolved from the variant field type's tag name (see
-\ref ctfirfieldtypes). If \p tag_name is \c NULL, it \em must be set
-with bt_field_type_variant_set_tag_name() \em before the variant
-field type is frozen.
-
-\p tag_name can be an absolute or relative reference. See
-<a href="http://diamon.org/ctf/">CTF</a> for more details.
-
-@param[in] tag_field_type Tag's enumeration field type
- (can be \c NULL).
-@param[in] tag_name Tag name (copied on success,
- can be \c NULL).
-@returns Created variant field type, or
- \c NULL on error.
-
-@pre \p tag_field_type is an enumeration field type or \c NULL.
-@post <strong>On success, if \p tag_field_type is not \c NULL</strong>,
- its reference count is incremented.
-@postsuccessrefcountret1
-*/
-extern struct bt_field_type *bt_field_type_variant_create(
- struct bt_field_type *tag_field_type,
- const char *tag_name);
-
-extern struct bt_field_type *bt_field_type_variant_borrow_tag_field_type(
- struct bt_field_type *variant_field_type);
-
-/**
-@brief Returns the tag's @enumft of the @varft \p variant_field_type.
-
-@param[in] variant_field_type Variant field type of which to get
- the tag's enumeration field type.
-@returns Tag's enumeration field type of
- \p variant_field_type, or \c NULL if the
- tag's field type is not set or on
- error.
-
-@prenotnull{variant_field_type}
-@preisvarft{variant_field_type}
-@postrefcountsame{variant_field_type}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field_type *bt_field_type_variant_get_tag_field_type(
- struct bt_field_type *variant_field_type)
-{
- return bt_get(bt_field_type_variant_borrow_tag_field_type(
- variant_field_type));
-}
-
-/**
-@brief Returns the tag name of the @varft \p variant_field_type.
-
-On success, \p variant_field_type remains the sole owner of
-the returned string.
-
-@param[in] variant_field_type Variant field type of which to get the
- tag name.
-@returns Tag name of \p variant_field_type, or
- \c NULL if the tag name is not set or
- on error.
-
-@prenotnull{variant_field_type}
-@preisvarft{variant_field_type}
-
-@sa bt_field_type_variant_set_tag_name(): Sets the tag name of
- a given variant field type.
-@sa bt_field_type_variant_get_tag_field_path(): Returns the tag's
- CTF IR field path of a given variant field type.
-*/
-extern const char *bt_field_type_variant_get_tag_name(
- struct bt_field_type *variant_field_type);
-
-/**
-@brief Sets the tag name of the @varft \p variant_field_type.
-
-\p tag_name can be an absolute or relative reference. See
-<a href="http://diamon.org/ctf/">CTF</a> for more details.
-
-@param[in] variant_field_type Variant field type of which to set
- the tag name.
-@param[in] tag_name Tag name of \p variant_field_type
- (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{variant_field_type}
-@prenotnull{name}
-@prehot{variant_field_type}
-@postrefcountsame{variant_field_type}
-
-@sa bt_field_type_variant_get_tag_name(): Returns the tag name of
- a given variant field type.
-*/
-extern int bt_field_type_variant_set_tag_name(
- struct bt_field_type *variant_field_type,
- const char *tag_name);
-
-extern struct bt_field_path *bt_field_type_variant_borrow_tag_field_path(
- struct bt_field_type *variant_field_type);
-
-/**
-@brief Returns the tag's CTF IR field path of the @varft
- \p variant_field_type.
-
-The tag's field path of a variant field type is set when automatic
-resolving is performed (see \ref ctfirfieldtypes).
-
-@param[in] variant_field_type Variant field type of which to get the
- tag's field path.
-@returns Tag's field path of
- \p variant_field_type, or
- \c NULL if the tag's field path is not
- set yet is not set or on error.
-
-@prenotnull{variant_field_type}
-@preisvarft{variant_field_type}
-@postsuccessrefcountretinc
-
-@sa bt_field_type_variant_get_tag_name(): Returns the tag's
- name of a given variant field type.
-*/
-static inline
-struct bt_field_path *bt_field_type_variant_get_tag_field_path(
- struct bt_field_type *variant_field_type)
-{
- return bt_get(bt_field_type_variant_borrow_tag_field_path(
- variant_field_type));
-}
-
-/**
-@brief Returns the number of fields (choices) contained in the @varft
- \p variant_field_type.
-
-@param[in] variant_field_type Variant field type of which to get
- the number of contained fields.
-@returns Number of fields contained in
- \p variant_field_type, or a negative
- value on error.
-
-@prenotnull{variant_field_type}
-@preisvarft{variant_field_type}
-@postrefcountsame{variant_field_type}
-*/
-extern int64_t bt_field_type_variant_get_field_count(
- struct bt_field_type *variant_field_type);
-
-extern int bt_field_type_variant_borrow_field_by_index(
- struct bt_field_type *variant_field_type,
- const char **field_name,
- struct bt_field_type **field_type, uint64_t index);
-
-/**
-@brief Returns the field (choice) of the @varft \p variant_field_type
- at index \p index.
-
-On success, the field's type is placed in \p *field_type if
-\p field_type is not \c NULL. The field's name is placed in
-\p *field_name if \p field_name is not \c NULL.
-\p variant_field_type remains the sole owner of \p *field_name.
-
-@param[in] variant_field_type Variant field type of which to get
- the field at index \p index.
-@param[out] field_name Returned name of the field at index
- \p index (can be \c NULL).
-@param[out] field_type Returned field type of the field
- at index \p index (can be \c NULL).
-Â@param[in] index Index of the field to get from
- \p variant_field_type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{variant_field_type}
-@preisvarft{variant_field_type}
-@pre \p index is lesser than the number of fields contained in the
- variant field type \p variant_field_type (see
- bt_field_type_variant_get_field_count()).
-@postrefcountsame{variant_field_type}
-@post <strong>On success</strong>, the returned field's type is placed
- in \p *field_type and its reference count is incremented.
+ struct bt_field_type *field_type);
-@sa bt_field_type_variant_get_field_type_by_name(): Finds a variant
- field type's field by name.
-@sa bt_field_type_variant_get_field_type_from_tag(): Finds a variant
- field type's field by current tag value.
-*/
-static inline
-int bt_field_type_variant_get_field_by_index(
- struct bt_field_type *variant_field_type,
- const char **field_name,
- struct bt_field_type **field_type, uint64_t index)
-{
- int ret = bt_field_type_variant_borrow_field_by_index(
- variant_field_type, field_name, field_type, index);
+extern uint64_t bt_field_type_static_array_get_length(
+ struct bt_field_type *field_type);
- if (ret == 0 && field_type) {
- bt_get(*field_type);
- }
+extern struct bt_field_path *
+bt_field_type_dynamic_array_borrow_length_field_path(
+ struct bt_field_type *field_type);
- return ret;
-}
+extern int bt_field_type_dynamic_array_set_length_field_type(
+ struct bt_field_type *field_type,
+ struct bt_field_type *length_field_type);
-extern
-struct bt_field_type *bt_field_type_variant_borrow_field_type_by_name(
- struct bt_field_type *variant_field_type,
- const char *field_name);
+extern struct bt_field_type *bt_field_type_variant_create(void);
-/**
-@brief Returns the type of the field (choice) named \p field_name
- found in the @varft \p variant_field_type.
+extern struct bt_field_path *
+bt_field_type_variant_borrow_selector_field_path(
+ struct bt_field_type *field_type);
-@param[in] variant_field_type Variant field type of which to get
- a field's type.
-@param[in] field_name Name of the field to find.
-@returns Type of the field named \p field_name in
- \p variant_field_type, or
- \c NULL on error.
+extern int bt_field_type_variant_set_selector_field_type(
+ struct bt_field_type *field_type,
+ struct bt_field_type *selector_field_type);
-@prenotnull{variant_field_type}
-@prenotnull{field_name}
-@preisvarft{variant_field_type}
-@postrefcountsame{variant_field_type}
-@postsuccessrefcountretinc
+extern uint64_t bt_field_type_variant_get_option_count(
+ struct bt_field_type *field_type);
-@sa bt_field_type_variant_get_field_by_index(): Finds a variant field type's
- field by index.
-@sa bt_field_type_variant_get_field_type_from_tag(): Finds a variant
- field type's field by current tag value.
-*/
-static inline
-struct bt_field_type *bt_field_type_variant_get_field_type_by_name(
- struct bt_field_type *variant_field_type,
- const char *field_name)
-{
- return bt_get(bt_field_type_variant_borrow_field_type_by_name(
- variant_field_type, field_name));
-}
+extern void bt_field_type_variant_borrow_option_by_index(
+ struct bt_field_type *variant_field_type, uint64_t index,
+ const char **name, struct bt_field_type **field_type);
extern
-struct bt_field_type *bt_field_type_variant_borrow_field_type_from_tag(
- struct bt_field_type *variant_field_type,
- struct bt_field *tag_field);
-
-/**
-@brief Returns the type of the field (choice) selected by the value of
- the @enumfield \p tag_field in the @varft \p variant_field_type.
-
-\p tag_field is the current tag value.
-
-The field type of \p tag_field, as returned by bt_field_get_type(),
-\em must be equivalent to the field type returned by
-bt_field_type_variant_get_tag_field_type() for \p variant_field_type.
-
-@param[in] variant_field_type Variant field type of which to get
- a field's type.
-@param[in] tag_field Current tag value (variant field type's
- selector).
-@returns Type of the field selected by
- \p tag_field in \p variant_field_type,
- or \c NULL on error.
-
-@prenotnull{variant_field_type}
-@prenotnull{tag_field}
-@preisvarft{variant_field_type}
-@preisenumfield{tag_field}
-@postrefcountsame{variant_field_type}
-@postrefcountsame{tag_field}
-@postsuccessrefcountretinc
-
-@sa bt_field_type_variant_get_field_by_index(): Finds a variant field type's
- field by index.
-@sa bt_field_type_variant_get_field_type_by_name(): Finds a variant
- field type's field by name.
-*/
-static inline
-struct bt_field_type *bt_field_type_variant_get_field_type_from_tag(
- struct bt_field_type *variant_field_type,
- struct bt_field *tag_field)
-{
- return bt_get(bt_field_type_variant_borrow_field_type_from_tag(
- variant_field_type, tag_field));
-}
-
-/**
-@brief Adds a field (a choice) named \p field_name with the @ft
- \p field_type to the @varft \p variant_field_type.
-
-On success, \p field_type becomes the child of \p variant_field_type.
-
-You \em cannot add a field named \p field_name if there's already a
-field named \p field_name in \p variant_field_type.
-
-\p field_name \em must name an existing mapping in the tag's
-enumeration field type of \p variant_field_type.
-
-@param[in] variant_field_type Variant field type to which to add
- a new field.
-@param[in] field_type Field type of the field to add to
- \p variant_field_type.
-@param[in] field_name Name of the field to add to
- \p variant_field_type
- (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{variant_field_type}
-@prenotnull{field_type}
-@prenotnull{field_name}
-@preisvarft{variant_field_type}
-@pre \p field_type is not and does not contain \p variant_field_type,
- recursively, as a field's type.
-@prehot{variant_field_type}
-@postrefcountsame{variant_field_type}
-@postsuccessrefcountinc{field_type}
-*/
-extern int bt_field_type_variant_add_field(
- struct bt_field_type *variant_field_type,
+struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name(
struct bt_field_type *field_type,
- const char *field_name);
+ const char *name);
-/** @} */
+extern int bt_field_type_variant_append_option(
+ struct bt_field_type *var_field_type,
+ const char *name, struct bt_field_type *field_type);
#ifdef __cplusplus
}
#include <glib.h>
#define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name) \
- BT_ASSERT_PRE((_field)->type->id == ((int) (_type_id)), \
+ BT_ASSERT_PRE(((struct bt_field *) (_field))->type->id == (_type_id), \
_name " has the wrong type ID: expected-type-id=%s, " \
- "%![field-]+f", \
- bt_common_field_type_id_string((int) (_type_id)), (_field))
-
-#define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \
- BT_ASSERT_PRE(bt_field_is_set_recursive(_field), \
+ "%![field-]+f", \
+ bt_common_field_type_id_string(_type_id), (_field))
+
+#define BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(_field, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER || \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, \
+ _name " is not an unsigned integer field: %![field-]+f", \
+ (_field))
+
+#define BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(_field, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_INTEGER || \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, \
+ _name " is not a signed integer field: %![field-]+f", \
+ (_field))
+
+#define BT_ASSERT_PRE_FIELD_IS_ARRAY(_field, _name) \
+ BT_ASSERT_PRE( \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_STATIC_ARRAY || \
+ ((struct bt_field *) (_field))->type->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, \
+ _name " is not an array field: %![field-]+f", (_field))
+
+#define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \
+ BT_ASSERT_PRE(bt_field_is_set(_field), \
_name " is not set: %!+f", (_field))
-#define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \
- BT_ASSERT_PRE_HOT((_field), (_name), ": %!+f", (_field))
+#define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \
+ BT_ASSERT_PRE_HOT((struct bt_field *) (_field), (_name), \
+ ": %!+f", (_field))
struct bt_field;
-typedef void (*bt_field_method_set_is_frozen)(struct bt_field *,
- bool);
-typedef int (*bt_field_method_validate)(struct bt_field *);
-typedef bt_bool (*bt_field_method_is_set)(struct bt_field *);
+typedef struct bt_field *(* bt_field_create_func)(struct bt_field_type *);
+typedef void (*bt_field_method_set_is_frozen)(struct bt_field *, bool);
+typedef bool (*bt_field_method_is_set)(struct bt_field *);
typedef void (*bt_field_method_reset)(struct bt_field *);
struct bt_field_methods {
bt_field_method_set_is_frozen set_is_frozen;
- bt_field_method_validate validate;
bt_field_method_is_set is_set;
bt_field_method_reset reset;
};
struct bt_field {
struct bt_object base;
+
+ /* Owned by this */
struct bt_field_type *type;
+
+ /* Virtual table for slow path (dev mode) operations */
struct bt_field_methods *methods;
- bool payload_set;
+
+ bool is_set;
bool frozen;
};
struct bt_field_integer {
struct bt_field common;
- union {
- int64_t signd;
- uint64_t unsignd;
- } payload;
-};
-struct bt_field_enumeration {
- struct bt_field_integer common;
+ union {
+ uint64_t u;
+ int64_t i;
+ } value;
};
-struct bt_field_floating_point {
+struct bt_field_real {
struct bt_field common;
- double payload;
+ double value;
};
struct bt_field_structure {
struct bt_field_variant {
struct bt_field common;
- union {
- uint64_t u;
- int64_t i;
- } tag_value;
+ /* Weak: belongs to `fields` below */
+ struct bt_field *selected_field;
- /* Weak: belongs to `choices` below */
- struct bt_field *current_field;
+ /* Index of currently selected field */
+ uint64_t selected_index;
/* Array of `struct bt_field *`, owned by this */
GPtrArray *fields;
struct bt_field common;
/* Array of `struct bt_field *`, owned by this */
- GPtrArray *elements;
-};
-
-struct bt_field_sequence {
- struct bt_field common;
+ GPtrArray *fields;
- /*
- * This is the true sequence field's length: its value can be
- * less than `elements->len` below because we never shrink the
- * array of elements to avoid reallocation.
- */
+ /* Current effective length */
uint64_t length;
-
- /* Array of `struct bt_field *`, owned by this */
- GPtrArray *elements;
};
struct bt_field_string {
struct bt_field common;
GArray *buf;
- size_t size;
+ uint64_t length;
};
#ifdef BT_DEV_MODE
-# define bt_field_validate_recursive _bt_field_validate_recursive
-# define bt_field_set_is_frozen_recursive _bt_field_set_is_frozen_recursive
-# define bt_field_is_set_recursive _bt_field_is_set_recursive
-# define bt_field_reset_recursive _bt_field_reset_recursive
-# define bt_field_set _bt_field_set
+# define bt_field_set_is_frozen _bt_field_set_is_frozen
+# define bt_field_is_set _bt_field_is_set
+# define bt_field_reset _bt_field_reset
+# define bt_field_set_single _bt_field_set_single
#else
-# define bt_field_validate_recursive(_field) (-1)
-# define bt_field_set_is_frozen_recursive(_field, _is_frozen)
-# define bt_field_is_set_recursive(_field) (BT_FALSE)
-# define bt_field_reset_recursive(_field)
-# define bt_field_set(_field, _val)
+# define bt_field_set_is_frozen(_field, _is_frozen)
+# define bt_field_is_set(_field) (BT_FALSE)
+# define bt_field_reset(_field)
+# define bt_field_set_single(_field, _val)
#endif
BT_HIDDEN
-void _bt_field_set_is_frozen_recursive(struct bt_field *field,
- bool is_frozen);
-
-static inline
-int _bt_field_validate_recursive(struct bt_field *field)
-{
- int ret = 0;
-
- if (!field) {
- BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
- ret = -1;
- goto end;
- }
-
- BT_ASSERT(bt_field_type_has_known_id(field->type));
-
- if (field->methods->validate) {
- ret = field->methods->validate(field);
- }
-
-end:
- return ret;
-}
+void _bt_field_set_is_frozen(struct bt_field *field, bool is_frozen);
static inline
-void _bt_field_reset_recursive(struct bt_field *field)
+void _bt_field_reset(struct bt_field *field)
{
BT_ASSERT(field);
BT_ASSERT(field->methods->reset);
}
static inline
-void _bt_field_set(struct bt_field *field, bool value)
+void _bt_field_set_single(struct bt_field *field, bool value)
{
BT_ASSERT(field);
- field->payload_set = value;
+ field->is_set = value;
}
static inline
-bt_bool _bt_field_is_set_recursive(struct bt_field *field)
+bt_bool _bt_field_is_set(struct bt_field *field)
{
bt_bool is_set = BT_FALSE;
}
BT_HIDDEN
-struct bt_field *bt_field_create_recursive(struct bt_field_type *type);
+struct bt_field *bt_field_create(struct bt_field_type *type);
BT_HIDDEN
-void bt_field_destroy_recursive(struct bt_field *field);
+void bt_field_destroy(struct bt_field *field);
#endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
*/
#include <stdint.h>
-#include <stddef.h>
-
-/* For bt_get() */
-#include <babeltrace/ref.h>
/* For bt_bool */
#include <babeltrace/types.h>
-/* For BT_FIELD_TYPE_ID_* */
+/* For enum bt_field_type_id */
#include <babeltrace/ctf-ir/field-types.h>
#ifdef __cplusplus
extern "C" {
#endif
-struct bt_field_type;
-
-/**
-@defgroup ctfirfields CTF IR fields
-@ingroup ctfir
-@brief CTF IR fields.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>field</em></strong> is an object which holds a
-concrete value, and which is described by a @ft.
-
-In the CTF IR hierarchy, you can set the root fields of two objects:
-
-- \ref ctfirpacket
- - Trace packet header field: bt_packet_set_header().
- - Stream packet context field: bt_packet_set_context().
-- \ref ctfirevent
- - Stream event header field: bt_event_set_header().
- - Stream event context field: bt_event_set_stream_event_context().
- - Event context field: bt_event_set_event_context().
- - Event payload field: bt_event_set_payload_field().
-
-There are two categories of fields:
-
-- <strong>Basic fields</strong>:
- - @intfield: contains an integral value.
- - @floatfield: contains a floating point number value.
- - @enumfield: contains an integer field which contains an integral
- value.
- - @stringfield: contains a string value.
-- <strong>Compound fields</strong>:
- - @structfield: contains an ordered list of named fields
- (possibly with different @fts).
- - @arrayfield: contains an ordered list of fields which share
- the same field type.
- - @seqfield: contains an ordered list of fields which share
- the same field type.
- - @varfield: contains a single, current field.
-
-You can create a field object from a @ft object with
-bt_field_create(). The enumeration and compound fields create their
-contained fields with the following getters if such fields do not exist
-yet:
-
-- bt_field_enumeration_get_container()
-- bt_field_structure_get_field_by_name()
-- bt_field_array_get_field()
-- bt_field_sequence_get_field()
-- bt_field_variant_get_field()
-
-If you already have a field object, you can also assign it to a specific
-name within a @structfield with
-bt_field_structure_set_field_by_name().
-
-You can get a reference to the @ft which was used to create a field with
-bt_field_get_type(). You can get the
-\link #bt_field_type_id type ID\endlink of this field type directly with
-bt_field_get_type_id().
-
-You can get a deep copy of a field with bt_field_copy(). The field
-copy, and its contained field copies if it's the case, have the same
-field type as the originals.
-
-As with any Babeltrace object, CTF IR field objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-The functions which freeze CTF IR \link ctfirpacket packet\endlink and
-\link ctfirevent event\endlink objects also freeze their root field
-objects. You cannot modify a frozen field object: it is considered
-immutable, except for \link refs reference counting\endlink.
-
-@sa ctfirfieldtypes
-
-@file
-@brief CTF IR fields type and functions.
-@sa ctfirfields
-
-@addtogroup ctfirfields
-@{
-*/
-
-/**
-@struct bt_field
-@brief A CTF IR field.
-@sa ctfirfields
-*/
struct bt_field;
-struct bt_event_class;
-struct bt_event;
struct bt_field_type;
struct bt_field_type_enumeration_mapping_iterator;
-/**
-@name Creation and parent field type access functions
-@{
-*/
-
extern struct bt_field_type *bt_field_borrow_type(struct bt_field *field);
-/**
-@brief Returns the parent @ft of the @field \p field.
-
-This function returns a reference to the field type which was used to
-create the field object in the first place with bt_field_create().
-
-@param[in] field Field of which to get the parent field type.
-@returns Parent field type of \p event,
- or \c NULL on error.
-
-@prenotnull{field}
-@postrefcountsame{field}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_field_type *bt_field_get_type(struct bt_field *field)
-{
- return bt_get(bt_field_borrow_type(field));
-}
-
-/** @} */
-
-/**
-@name Type information
-@{
-*/
-
-/**
-@brief Returns the type ID of the @ft of the @field \p field.
-
-@param[in] field Field of which to get the type ID of its
- parent field type..
-@returns Type ID of the parent field type of \p field,
- or #BT_FIELD_TYPE_ID_UNKNOWN on error.
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa #bt_field_type_id: CTF IR field type ID.
-@sa bt_field_is_integer(): Returns whether or not a given field is a
- @intfield.
-@sa bt_field_is_floating_point(): Returns whether or not a given
- field is a @floatfield.
-@sa bt_field_is_enumeration(): Returns whether or not a given field
- is a @enumfield.
-@sa bt_field_is_string(): Returns whether or not a given field is a
- @stringfield.
-@sa bt_field_is_structure(): Returns whether or not a given field is
- a @structfield.
-@sa bt_field_is_array(): Returns whether or not a given field is a
- @arrayfield.
-@sa bt_field_is_sequence(): Returns whether or not a given field is
- a @seqfield.
-@sa bt_field_is_variant(): Returns whether or not a given field is a
- @varfield.
-*/
extern enum bt_field_type_id bt_field_get_type_id(struct bt_field *field);
-/**
-@brief Returns whether or not the @field \p field is a @intfield.
-
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is an integer field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_integer(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_INTEGER;
-}
-
-/**
-@brief Returns whether or not the @field \p field is a @floatfield.
-
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is a floating point number fiel
- #BT_FALSE or 0 otherwise (including if \p field is
- \c NULL).
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_floating_point(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_FLOAT;
-}
-
-/**
-@brief Returns whether or not the @field \p field is a @enumfield.
-
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is an enumeration field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_enumeration(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ENUM;
-}
-
-/**
-@brief Returns whether or not the @field \p field is a @stringfield.
-
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is a string field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
+extern int64_t bt_field_signed_integer_get_value(struct bt_field *field);
-@prenotnull{field}
-@postrefcountsame{field}
+extern void bt_field_signed_integer_set_value(struct bt_field *field,
+ int64_t value);
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_string(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING;
-}
-
-/**
-@brief Returns whether or not the @field \p field is a @structfield.
+extern uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field);
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is a structure field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
+extern void bt_field_unsigned_integer_set_value(struct bt_field *field,
+ uint64_t value);
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_structure(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRUCT;
-}
+extern double bt_field_real_get_value(struct bt_field *field);
-/**
-@brief Returns whether or not the @field \p field is a @arrayfield.
+extern void bt_field_real_set_value(struct bt_field *field, double value);
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is an array field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_array(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ARRAY;
-}
+extern int bt_field_unsigned_enumeration_get_mapping_labels(
+ struct bt_field *field,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count);
-/**
-@brief Returns whether or not the @field \p field is a @seqfield.
+extern int bt_field_signed_enumeration_get_mapping_labels(
+ struct bt_field *field,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count);
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is a sequence field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
+extern const char *bt_field_string_get_value(struct bt_field *field);
-@prenotnull{field}
-@postrefcountsame{field}
+extern uint64_t bt_field_string_get_length(struct bt_field *field);
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_sequence(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SEQUENCE;
-}
-
-/**
-@brief Returns whether or not the @field \p field is a @varfield.
-
-@param[in] field Field to check (can be \c NULL).
-@returns #BT_TRUE if \p field is a variant field, or
- #BT_FALSE otherwise (including if \p field is
- \c NULL).
-
-@prenotnull{field}
-@postrefcountsame{field}
-
-@sa bt_field_get_type_id(): Returns the type ID of a given
- field's type.
-*/
-static inline
-bt_bool bt_field_is_variant(struct bt_field *field)
-{
- return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT;
-}
+extern int bt_field_string_set_value(struct bt_field *field, const char *value);
-/** @} */
-
-/**
-@name Misc. functions
-@{
-*/
-
-/** @} */
-
-/** @} */
-
-/**
-@defgroup ctfirintfield CTF IR integer field
-@ingroup ctfirfields
-@brief CTF IR integer field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>integer field</em></strong> is a @field which
-holds a signed or unsigned integral value, and which is described by
-a @intft.
-
-An integer field object is considered \em unsigned if
-bt_field_type_integer_get_signed() on its parent field type returns
-0. Otherwise it is considered \em signed. You \em must use
-bt_field_integer_unsigned_get_value() and
-bt_field_integer_unsigned_set_value() with an unsigned integer
-field, and bt_field_integer_signed_get_value() and
-bt_field_integer_signed_set_value() with a signed integer field.
-
-After you create an integer field with bt_field_create(), you
-\em must set an integral value with
-bt_field_integer_unsigned_set_value() or
-bt_field_integer_signed_set_value() before you can get the
-field's value with bt_field_integer_unsigned_get_value() or
-bt_field_integer_signed_get_value().
-
-@sa ctfirintfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirintfield
-@{
-*/
-
-/**
-@brief Returns the signed integral value of the @intfield
- \p integer_field.
-
-@param[in] integer_field Integer field of which to get the
- signed integral value.
-@param[out] value Returned signed integral value of
- \p integer_field.
-@returns 0 on success, or a negative value on
- error, including if \p integer_field
- has no integral value yet.
-
-@prenotnull{integer_field}
-@prenotnull{value}
-@preisintfield{integer_field}
-@pre bt_field_type_integer_get_signed() returns 1 for the parent
- @ft of \p integer_field.
-@pre \p integer_field contains a signed integral value previously
- set with bt_field_integer_signed_set_value().
-@postrefcountsame{integer_field}
-
-@sa bt_field_integer_signed_set_value(): Sets the signed integral
- value of a given integer field.
-*/
-extern int bt_field_integer_signed_get_value(
- struct bt_field *integer_field, int64_t *value);
-
-/**
-@brief Sets the signed integral value of the @intfield
- \p integer_field to \p value.
-
-@param[in] integer_field Integer field of which to set
- the signed integral value.
-@param[in] value New signed integral value of
- \p integer_field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{integer_field}
-@preisintfield{integer_field}
-@prehot{integer_field}
-@pre bt_field_type_integer_get_signed() returns 1 for the parent
- @ft of \p integer_field.
-@postrefcountsame{integer_field}
-
-@sa bt_field_integer_signed_get_value(): Returns the signed integral
- value of a given integer field.
-*/
-extern int bt_field_integer_signed_set_value(
- struct bt_field *integer_field, int64_t value);
-
-/**
-@brief Returns the unsigned integral value of the @intfield
- \p integer_field.
-
-@param[in] integer_field Integer field of which to get the
- unsigned integral value.
-@param[out] value Returned unsigned integral value of
- \p integer_field.
-@returns 0 on success, or a negative value on
- error, including if \p integer_field
- has no integral value yet.
-
-@prenotnull{integer_field}
-@prenotnull{value}
-@preisintfield{integer_field}
-@pre bt_field_type_integer_get_signed() returns 0 for the parent
- @ft of \p integer_field.
-@pre \p integer_field contains an unsigned integral value previously
- set with bt_field_integer_unsigned_set_value().
-@postrefcountsame{integer_field}
-
-@sa bt_field_integer_unsigned_set_value(): Sets the unsigned
- integral value of a given integer field.
-*/
-extern int bt_field_integer_unsigned_get_value(
- struct bt_field *integer_field, uint64_t *value);
-
-/**
-@brief Sets the unsigned integral value of the @intfield
- \p integer_field to \p value.
-
-@param[in] integer_field Integer field of which to set
- the unsigned integral value.
-@param[in] value New unsigned integral value of
- \p integer_field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{integer_field}
-@preisintfield{integer_field}
-@prehot{integer_field}
-@pre bt_field_type_integer_get_signed() returns 0 for the parent
- @ft of \p integer_field.
-@postrefcountsame{integer_field}
-
-@sa bt_field_integer_unsigned_get_value(): Returns the unsigned
- integral value of a given integer field.
-*/
-extern int bt_field_integer_unsigned_set_value(
- struct bt_field *integer_field, uint64_t value);
-
-/** @} */
-
-/**
-@defgroup ctfirfloatfield CTF IR floating point number field
-@ingroup ctfirfields
-@brief CTF IR floating point number field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>floating point number field</em></strong> is a
-@field which holds a floating point number value, and which is
-described by a @floatft.
-
-After you create a floating point number field with bt_field_create(), you
-\em must set a floating point number value with
-bt_field_floating_point_set_value() before you can get the
-field's value with bt_field_floating_point_get_value().
-
-@sa ctfirfloatfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirfloatfield
-@{
-*/
-
-/**
-@brief Returns the floating point number value of the @floatfield
- \p float_field.
-
-@param[in] float_field Floating point number field of which to get the
- floating point number value.
-@param[out] value Returned floating point number value of
- \p float_field.
-@returns 0 on success, or a negative value on error,
- including if \p float_field has no floating
- point number value yet.
-
-@prenotnull{float_field}
-@prenotnull{value}
-@preisfloatfield{float_field}
-@pre \p float_field contains a floating point number value previously
- set with bt_field_floating_point_set_value().
-@postrefcountsame{float_field}
-
-@sa bt_field_floating_point_set_value(): Sets the floating point
- number value of a given floating point number field.
-*/
-extern int bt_field_floating_point_get_value(
- struct bt_field *float_field, double *value);
-
-/**
-@brief Sets the floating point number value of the @floatfield
- \p float_field to \p value.
-
-@param[in] float_field Floating point number field of which to set
- the floating point number value.
-@param[in] value New floating point number value of
- \p float_field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{float_field}
-@preisfloatfield{float_field}
-@prehot{float_field}
-@postrefcountsame{float_field}
-
-@sa bt_field_floating_point_get_value(): Returns the floating point
- number value of a given floating point number field.
-*/
-extern int bt_field_floating_point_set_value(
- struct bt_field *float_field, double value);
-
-/** @} */
-
-/**
-@brief Returns a @enumftiter on all the mappings of the field type of
- \p enum_field which contain the current integral value of the
- @enumfield \p enum_field in their range.
-
-This function is the equivalent of using
-bt_field_type_enumeration_find_mappings_by_unsigned_value() or
-bt_field_type_enumeration_find_mappings_by_signed_value() with the
-current integral value of \p enum_field.
-
-@param[in] enum_field Enumeration field of which to get the mappings
- containing the current integral value of \p
- enum_field in their range.
-@returns @enumftiter on the set of mappings of the field
- type of \p enum_field which contain the current
- integral value of \p enum_field in their range,
- or \c NULL if no mappings were found or on
- error.
-
-@prenotnull{enum_field}
-@preisenumfield{enum_field}
-@pre The wrapped integer field of \p enum_field contains an integral
- value.
-@postrefcountsame{enum_field}
-@postsuccessrefcountret1
-@post <strong>On success</strong>, the returned @enumftiter can iterate
- on at least one mapping.
-*/
-extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_enumeration_get_mappings(struct bt_field *enum_field);
-
-/** @} */
-
-/**
-@defgroup ctfirstringfield CTF IR string field
-@ingroup ctfirfields
-@brief CTF IR string field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>string field</em></strong> is a @field which holds
-a string value, and which is described by a @stringft.
-
-Use bt_field_string_set_value() to set the current string value
-of a string field object. You can also use bt_field_string_append()
-and bt_field_string_append_len() to append a string to the current
-value of a string field.
-
-After you create a string field with bt_field_create(), you
-\em must set a string value with
-bt_field_string_set_value(), bt_field_string_append(), or
-bt_field_string_append_len() before you can get the
-field's value with bt_field_string_get_value().
-
-@sa ctfirstringfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirstringfield
-@{
-*/
-
-/**
-@brief Returns the string value of the @stringfield \p string_field.
-
-On success, \p string_field remains the sole owner of the returned
-value.
-
-@param[in] string_field String field field of which to get the
- string value.
-@returns String value, or \c NULL on error.
-
-@prenotnull{string_field}
-@prenotnull{value}
-@preisstringfield{string_field}
-@pre \p string_field contains a string value previously
- set with bt_field_string_set_value(),
- bt_field_string_append(), or
- bt_field_string_append_len().
-@postrefcountsame{string_field}
-
-@sa bt_field_string_set_value(): Sets the string value of a given
- string field.
-*/
-extern const char *bt_field_string_get_value(struct bt_field *string_field);
-
-/**
-@brief Sets the string value of the @stringfield \p string_field to
- \p value.
-
-@param[in] string_field String field of which to set
- the string value.
-@param[in] value New string value of \p string_field (copied
- on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{string_field}
-@prenotnull{value}
-@preisstringfield{string_field}
-@prehot{string_field}
-@postrefcountsame{string_field}
-
-@sa bt_field_string_get_value(): Returns the string value of a
- given string field.
-*/
-extern int bt_field_string_set_value(struct bt_field *string_field,
- const char *value);
-
-/**
-@brief Appends the string \p value to the current string value of
- the @stringfield \p string_field.
-
-This function is the equivalent of:
-
-@code
-bt_field_string_append_len(string_field, value, strlen(value));
-@endcode
-
-@param[in] string_field String field of which to append \p value to
- its current value.
-@param[in] value String to append to the current string value
- of \p string_field (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{string_field}
-@prenotnull{value}
-@preisstringfield{string_field}
-@prehot{string_field}
-@postrefcountsame{string_field}
-
-@sa bt_field_string_set_value(): Sets the string value of a given
- string field.
-*/
-extern int bt_field_string_append(struct bt_field *string_field,
- const char *value);
-
-/**
-@brief Appends the first \p length characters of \p value to the
- current string value of the @stringfield \p string_field.
-
-If \p string_field has no current string value, this function first
-sets an empty string as the string value of \p string_field and then
-appends the first \p length characters of \p value.
-
-@param[in] string_field String field of which to append the first
- \p length characters of \p value to
- its current value.
-@param[in] value String containing the characters to append to
- the current string value of \p string_field
- (copied on success).
-@param[in] length Number of characters of \p value to append to
- the current string value of \p string_field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{string_field}
-@prenotnull{value}
-@preisstringfield{string_field}
-@prehot{string_field}
-@postrefcountsame{string_field}
-
-@sa bt_field_string_set_value(): Sets the string value of a given
- string field.
-*/
-extern int bt_field_string_append_len(
- struct bt_field *string_field, const char *value,
- unsigned int length);
-
-extern int bt_field_string_clear(struct bt_field *string_field);
-
-/** @} */
-
-/**
-@defgroup ctfirstructfield CTF IR structure field
-@ingroup ctfirfields
-@brief CTF IR structure field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>structure field</em></strong> is a @field which
-contains an ordered list of zero or more named @fields which can be
-different @fts, and which is described by a @structft.
-
-To set the value of a specific field of a structure field, you need to
-first get the field with bt_field_structure_get_field_by_name() or
-bt_field_structure_get_field_by_index(). If you already have a
-field object, you can assign it to a specific name within a structure
-field with bt_field_structure_set_field_by_name().
-
-@sa ctfirstructfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirstructfield
-@{
-*/
-
-extern struct bt_field *bt_field_structure_borrow_field_by_name(
- struct bt_field *struct_field, const char *name);
-
-extern struct bt_field *bt_field_structure_borrow_field_by_index(
- struct bt_field *struct_field, uint64_t index);
-
-/** @} */
-
-/**
-@defgroup ctfirarrayfield CTF IR array field
-@ingroup ctfirfields
-@brief CTF IR array field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>array field</em></strong> is a @field which
-contains an ordered list of zero or more @fields sharing the same @ft,
-and which is described by a @arrayft.
-
-To set the value of a specific field of an array field, you need to
-first get the field with bt_field_array_get_field().
-
-@sa ctfirarrayfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirarrayfield
-@{
-*/
-
-extern struct bt_field *bt_field_array_borrow_field(
- struct bt_field *array_field, uint64_t index);
-
-/** @} */
-
-/**
-@defgroup ctfirseqfield CTF IR sequence field
-@ingroup ctfirfields
-@brief CTF IR sequence field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>sequence field</em></strong> is a @field which
-contains an ordered list of zero or more @fields sharing the same @ft,
-and which is described by a @seqft.
-
-Before you can get a specific field of a sequence field with
-bt_field_sequence_get_field(), you need to set its current length
-@intfield with bt_field_sequence_set_length(). The integral value of
-the length field of a sequence field indicates the number of fields
-it contains.
+extern int bt_field_string_append(struct bt_field *field, const char *value);
-@sa ctfirseqfieldtype
-@sa ctfirfields
+extern int bt_field_string_append_with_length(struct bt_field *field,
+ const char *value, uint64_t length);
-@addtogroup ctfirseqfield
-@{
-*/
+extern int bt_field_string_clear(struct bt_field *field);
-extern struct bt_field *bt_field_sequence_borrow_field(
- struct bt_field *sequence_field, uint64_t index);
+extern struct bt_field *bt_field_structure_borrow_member_field_by_index(
+ struct bt_field *field, uint64_t index);
-extern int64_t bt_field_sequence_get_length(struct bt_field *sequence_field);
+extern struct bt_field *bt_field_structure_borrow_member_field_by_name(
+ struct bt_field *field, const char *name);
-/**
-@brief Sets the length @intfield of the @seqfield \p sequence_field
- to \p length_field.
+extern uint64_t bt_field_array_get_length(struct bt_field *field);
-The current integral value of \p length_field indicates the number of
-fields contained in \p sequence_field.
+extern struct bt_field *bt_field_array_borrow_element_field_by_index(
+ struct bt_field *field, uint64_t index);
-@param[in] sequence_field Sequence field of which to set the
- length field.
-@param[in] length_field Length field of \p sequence_field.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{sequence_field}
-@prenotnull{length_field}
-@preisseqfield{sequence_field}
-@preisintfield{length_field}
-@prehot{sequence_field}
-@postrefcountsame{sequence_field}
-@postsuccessrefcountinc{length_field}
-
-@sa bt_field_sequence_get_length(): Returns the length field of a
- given sequence field.
-*/
-extern int bt_field_sequence_set_length(struct bt_field *sequence_field,
+extern int bt_field_dynamic_array_set_length(struct bt_field *field,
uint64_t length);
-/** @} */
-
-/**
-@defgroup ctfirvarfield CTF IR variant field
-@ingroup ctfirfields
-@brief CTF IR variant field.
-
-@code
-#include <babeltrace/ctf-ir/fields.h>
-@endcode
-
-A CTF IR <strong><em>variant field</em></strong> is a @field which
-contains a current @field amongst one or more choices, and which is
-described by a @varft.
-
-Use bt_field_variant_get_field() to get the @field selected by
-a specific tag @enumfield. Once you call this function, you can call
-bt_field_variant_get_current_field() afterwards to get this last
-field again.
-
-@sa ctfirvarfieldtype
-@sa ctfirfields
-
-@addtogroup ctfirvarfield
-@{
-*/
-
-extern int bt_field_variant_set_tag_signed(struct bt_field *variant_field,
- int64_t tag);
-
-extern int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field,
- uint64_t tag);
-
-extern int bt_field_variant_get_tag_signed(struct bt_field *variant_field,
- int64_t *tag);
-
-extern int bt_field_variant_get_tag_unsigned(struct bt_field *variant_field,
- uint64_t *tag);
+extern int bt_field_variant_select_option_field(struct bt_field *field,
+ uint64_t index);
-extern struct bt_field *bt_field_variant_borrow_current_field(
- struct bt_field *variant_field);
+extern uint64_t bt_field_variant_get_selected_option_field_index(
+ struct bt_field *field);
-/** @} */
+extern struct bt_field *bt_field_variant_borrow_selected_option_field(
+ struct bt_field *field);
#ifdef __cplusplus
}
extern "C" {
#endif
+struct bt_stream_class;
struct bt_packet_context_field;
struct bt_field;
+extern
+struct bt_packet_context_field *bt_packet_context_field_create(
+ struct bt_stream_class *stream_class);
+
extern
struct bt_field *bt_packet_context_field_borrow_field(
struct bt_packet_context_field *field);
extern "C" {
#endif
+struct bt_trace;
struct bt_packet_header_field;
struct bt_field;
+extern
+struct bt_packet_header_field *bt_packet_header_field_create(
+ struct bt_trace *trace);
+
extern
struct bt_field *bt_packet_header_field_borrow_field(
struct bt_packet_header_field *field);
#include <stdbool.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/ctf-ir/clock-value.h>
#include <babeltrace/ctf-ir/packet.h>
#include <babeltrace/ctf-ir/fields.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/clock-value-set-internal.h>
-
-struct bt_packet_prop_uint64 {
- enum bt_packet_property_availability avail;
- uint64_t value;
-};
+#include <babeltrace/property-internal.h>
struct bt_packet {
struct bt_object base;
- struct bt_field_wrapper *header;
- struct bt_field_wrapper *context;
+ struct bt_field_wrapper *header_field;
+ struct bt_field_wrapper *context_field;
struct bt_stream *stream;
- struct bt_clock_value_set begin_cv_set;
- struct bt_clock_value_set end_cv_set;
- struct bt_packet_prop_uint64 discarded_event_counter;
- struct bt_packet_prop_uint64 seq_num;
- struct bt_packet_prop_uint64 discarded_event_count;
- struct bt_packet_prop_uint64 discarded_packet_count;
- bool props_are_set;
-
- struct {
- /*
- * We keep this here to avoid keeping a reference on the
- * previous packet object: those properties are
- * snapshots of the previous packet's properties when
- * calling bt_packet_create(). We know that the previous
- * packet's properties do not change afterwards because
- * we freeze the previous packet when bt_packet_create()
- * is successful.
- */
- enum bt_packet_previous_packet_availability avail;
- struct bt_packet_prop_uint64 discarded_event_counter;
- struct bt_packet_prop_uint64 seq_num;
- struct {
- enum bt_packet_property_availability avail;
-
- /* Owned by this (copy of previous packet's or NULL) */
- struct bt_clock_value *cv;
- } default_end_cv;
- } prev_packet_info;
-
- int frozen;
+ struct bt_clock_value *default_beginning_cv;
+ struct bt_clock_value *default_end_cv;
+ struct bt_property_uint discarded_event_counter_snapshot;
+ struct bt_property_uint packet_counter_snapshot;
+ bool frozen;
};
BT_HIDDEN
BT_HIDDEN
void bt_packet_destroy(struct bt_packet *packet);
-/*
- * Sets a packet's properties using its current context fields and its
- * previous packet's snapshotted properties (if any). The packet context
- * field must not be modified until the packet is recycled.
- *
- * This function does NOT set the `props_are_set` flag (does not
- * validate the properties): call bt_packet_validate_properties() to
- * mark the properties as definitely cached.
- */
-BT_HIDDEN
-int bt_packet_set_properties(struct bt_packet *packet);
-
-static inline
-void bt_packet_invalidate_properties(struct bt_packet *packet)
-{
- BT_ASSERT(packet);
- packet->props_are_set = false;
-}
-
-static inline
-void bt_packet_validate_properties(struct bt_packet *packet)
-{
- BT_ASSERT(packet);
- packet->props_are_set = true;
-}
-
#endif /* BABELTRACE_CTF_IR_PACKET_INTERNAL_H */
#include <stdint.h>
-/* For bt_get() */
-#include <babeltrace/ref.h>
+/* For enum bt_property_availability */
+#include <babeltrace/property.h>
-/* For bt_bool */
-#include <babeltrace/types.h>
+/* For enum bt_clock_value_status */
+#include <babeltrace/ctf-ir/clock-value.h>
#ifdef __cplusplus
extern "C" {
#endif
-/**
-@defgroup ctfirpacket CTF IR packet
-@ingroup ctfir
-@brief CTF IR packet.
-
-@code
-#include <babeltrace/ctf-ir/packet.h>
-@endcode
-
-A CTF IR <strong><em>packet</em></strong> is a container of packet
-fields, that is, of the <strong>trace packet header</strong> and
-<strong>stream packet context</strong> fields.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-You can create a CTF IR packet \em from a
-\link ctfirstream CTF IR stream\endlink with bt_packet_create(). The
-stream you use to create a packet object becomes its parent.
-
-When you set the trace packet header and stream packet context fields of
-a packet with resp. bt_packet_set_header() and
-bt_packet_set_context(), their field type \em must be equivalent to
-the field types returned by resp. bt_trace_get_packet_header_type()
-and bt_stream_class_get_packet_context_type() for its parent trace
-class and stream class.
-
-You can attach a packet object to a \link ctfirevent CTF IR
-event\endlink object with bt_event_set_packet().
-
-As with any Babeltrace object, CTF IR packet objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-bt_notification_event_create() \em freezes its event parameter on
-success, which in turns freezes the event's associated packet object.
-This is the only way that a CTF IR packet object can be frozen.
-You cannot modify a frozen packet: it is considered immutable,
-except for \link refs reference counting\endlink.
-
-@sa ctfirstream
-@sa ctfirstreamclass
-@sa ctfirtraceclass
-
-@file
-@brief CTF IR packet type and functions.
-@sa ctfirpacket
-
-@addtogroup ctfirpacket
-@{
-*/
-
-/**
-@struct bt_packet
-@brief A CTF IR packet.
-@sa ctfirpacket
-*/
struct bt_packet;
struct bt_packet_header_field;
struct bt_packet_context_field;
struct bt_stream;
struct bt_clock_value;
-struct bt_clock_class;
-
-enum bt_packet_previous_packet_availability {
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_ERROR = -1,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE,
-};
-
-enum bt_packet_property_availability {
- BT_PACKET_PROPERTY_AVAILABILITY_ERROR = -1,
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE,
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE,
-};
-
-/**
-@name Creation and parent access functions
-@{
-*/
-
-/**
-@brief Creates a default CTF IR packet with \p stream as its parent
- CTF IR stream.
-
-On success, the packet object's trace packet header and stream packet
-context fields are not set. You can set them with resp.
-bt_packet_set_header() and bt_packet_set_context().
-
-@param[in] stream Parent CTF IR stream of the packet to create.
-@returns Created packet, or \c NULL on error.
-
-@prenotnull{stream}
-@postsuccessrefcountret1
-*/
-extern struct bt_packet *bt_packet_create(struct bt_stream *stream,
- enum bt_packet_previous_packet_availability previous_packet_availability,
- struct bt_packet *previous_packet);
-extern struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet);
-
-/**
-@brief Returns the parent CTF IR stream of the CTF IR packet \p packet.
-
-This function returns a reference to the stream which was used to create
-the packet object in the first place with bt_packet_create().
-
-@param[in] packet Packet of which to get the parent stream.
-@returns Parent stream of \p packet, or \c NULL on error.
-
-@prenotnull{packet}
-@postrefcountsame{packet}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_stream *bt_packet_get_stream(
- struct bt_packet *packet)
-{
- return bt_get(bt_packet_borrow_stream(packet));
-}
-
-/** @} */
+extern struct bt_packet *bt_packet_create(struct bt_stream *stream);
-/**
-@name Contained fields functions
-@{
-*/
+extern struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet);
extern
-struct bt_field *bt_packet_borrow_header(struct bt_packet *packet);
+struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet);
extern
-int bt_packet_move_header(struct bt_packet *packet,
+int bt_packet_move_header_field(struct bt_packet *packet,
struct bt_packet_header_field *header);
extern
-struct bt_field *bt_packet_borrow_context(struct bt_packet *packet);
+struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet);
extern
-int bt_packet_move_context(struct bt_packet *packet,
+int bt_packet_move_context_field(struct bt_packet *packet,
struct bt_packet_context_field *context);
-/** @} */
-
-extern
-enum bt_packet_property_availability
-bt_packet_borrow_default_beginning_clock_value(struct bt_packet *packet,
- struct bt_clock_value **clock_value);
-
extern
-enum bt_packet_property_availability
-bt_packet_borrow_default_end_clock_value(struct bt_packet *packet,
- struct bt_clock_value **clock_value);
+enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value(
+ struct bt_packet *packet, struct bt_clock_value **clock_value);
extern
-enum bt_packet_previous_packet_availability
-bt_packet_get_previous_packet_availability(struct bt_packet *packet);
+int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet,
+ uint64_t value_cycles);
extern
-enum bt_packet_property_availability
-bt_packet_borrow_previous_packet_default_end_clock_value(
+enum bt_clock_value_status bt_packet_borrow_default_end_clock_valeu(
struct bt_packet *packet, struct bt_clock_value **clock_value);
extern
-enum bt_packet_property_availability bt_packet_get_discarded_event_counter(
- struct bt_packet *packet, uint64_t *counter);
+int bt_packet_set_default_end_clock_value(struct bt_packet *packet,
+ uint64_t value_cycles);
extern
-enum bt_packet_property_availability bt_packet_get_sequence_number(
- struct bt_packet *packet, uint64_t *sequence_number);
+enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot(
+ struct bt_packet *packet, uint64_t *value);
extern
-enum bt_packet_property_availability bt_packet_get_discarded_event_count(
- struct bt_packet *packet, uint64_t *count);
+int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet,
+ uint64_t value);
extern
-enum bt_packet_property_availability bt_packet_get_discarded_packet_count(
- struct bt_packet *packet, uint64_t *count);
+enum bt_property_availability bt_packet_get_packet_counter_snapshot(
+ struct bt_packet *packet, uint64_t *value);
-/** @} */
+extern
+int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet,
+ uint64_t value);
#ifdef __cplusplus
}
--- /dev/null
+#ifndef BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL
+#define BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL
+
+/*
+ * BabelTrace - CTF IR: Field path
+ *
+ * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/object-internal.h>
+#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-ir/field-path.h>
+#include <glib.h>
+
+struct bt_resolve_field_path_context {
+ struct bt_field_type *packet_header;
+ struct bt_field_type *packet_context;
+ struct bt_field_type *event_header;
+ struct bt_field_type *event_common_context;
+ struct bt_field_type *event_specific_context;
+ struct bt_field_type *event_payload;
+};
+
+BT_HIDDEN
+int bt_resolve_field_paths(struct bt_field_type *ft,
+ struct bt_resolve_field_path_context *ctx);
+
+#endif /* BABELTRACE_CTF_IR_RESOLVE_FIELD_PATH_INTERNAL */
#include <babeltrace/assert-internal.h>
#include <babeltrace/common-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/utils-internal.h>
-#include <babeltrace/ctf-ir/visitor.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/object-pool-internal.h>
struct bt_stream_class {
struct bt_object base;
- GString *name;
- /* Array of pointers to event class addresses */
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } name;
+
+ uint64_t id;
+ bool assigns_automatic_event_class_id;
+ bool assigns_automatic_stream_id;
+ bool packets_have_discarded_event_counter_snapshot;
+ bool packets_have_packet_counter_snapshot;
+ bool packets_have_default_beginning_cv;
+ bool packets_have_default_end_cv;
+ struct bt_field_type *packet_context_ft;
+ struct bt_field_type *event_header_ft;
+ struct bt_field_type *event_common_context_ft;
+ struct bt_clock_class *default_clock_class;
+
+ /* Array of `struct bt_event_class *` */
GPtrArray *event_classes;
- /* event class id (int64_t) to event class address */
- GHashTable *event_classes_ht;
- int id_set;
- int64_t id;
- int64_t next_event_id;
- struct bt_field_type *packet_context_field_type;
- struct bt_field_type *event_header_field_type;
- struct bt_field_type *event_context_field_type;
- int frozen;
- int byte_order;
-
- /*
- * This flag indicates if the stream class is valid. A valid
- * stream class is _always_ frozen.
- */
- int valid;
-
- /*
- * Unique clock class mapped to any field type within this
- * stream class, including all the stream class's event class
- * field types. This is only set if the stream class is frozen.
- *
- * If the stream class is frozen and this is still NULL, it is
- * still possible that it becomes non-NULL because
- * bt_stream_class_add_event_class() can add an event class
- * containing a field type mapped to some clock class. In this
- * case, this is the mapped clock class, and at this point, both
- * the new event class and the stream class are frozen, so the
- * next added event classes are expected to contain field types
- * which only map to this specific clock class.
- *
- * If this is a CTF writer stream class, then this is the
- * backing clock class of the `clock` member above.
- */
- struct bt_clock_class *clock_class;
-
/* Pool of `struct bt_field_wrapper *` */
struct bt_object_pool event_header_field_pool;
/* Pool of `struct bt_field_wrapper *` */
struct bt_object_pool packet_context_field_pool;
-};
-
-struct bt_event_class;
-BT_HIDDEN
-void bt_stream_class_freeze(struct bt_stream_class *stream_class);
+ bool frozen;
+};
BT_HIDDEN
-int bt_stream_class_validate_single_clock_class(
- struct bt_stream_class *stream_class,
- struct bt_clock_class **expected_clock_class);
+void _bt_stream_class_freeze(struct bt_stream_class *stream_class);
-BT_HIDDEN
-int bt_stream_class_visit(struct bt_stream_class *stream_class,
- bt_visitor visitor, void *data);
+#ifdef BT_DEV_MODE
+# define bt_stream_class_freeze _bt_stream_class_freeze
+#else
+# define bt_stream_class_freeze(_sc)
+#endif
static inline
-void _bt_stream_class_set_id(
- struct bt_stream_class *stream_class, int64_t id)
+struct bt_trace *bt_stream_class_borrow_trace_inline(
+ struct bt_stream_class *stream_class)
{
BT_ASSERT(stream_class);
- stream_class->id = id;
- stream_class->id_set = 1;
- BT_LOGV("Set stream class's ID (internal): "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
-}
-
-static inline
-int bt_stream_class_set_id_no_check(
- struct bt_stream_class *stream_class, int64_t id)
-{
- _bt_stream_class_set_id(stream_class, id);
- return 0;
+ return (void *) bt_object_borrow_parent(&stream_class->base);
}
#endif /* BABELTRACE_CTF_IR_STREAM_CLASS_INTERNAL_H */
#include <stdint.h>
-/* For bt_get() */
-#include <babeltrace/ref.h>
-
-/* For bt_visitor */
-#include <babeltrace/ctf-ir/visitor.h>
+/* For bt_bool */
+#include <babeltrace/types.h>
#ifdef __cplusplus
extern "C" {
#endif
-/**
-@defgroup ctfirstreamclass CTF IR stream class
-@ingroup ctfir
-@brief CTF IR stream class.
-
-@code
-#include <babeltrace/ctf-ir/stream-class.h>
-@endcode
-
-@note
-See \ref ctfwriterstreamclass which documents additional CTF IR stream
-class functions exclusive to the CTF writer mode.
-
-A CTF IR <strong><em>stream class</em></strong> is a template that you
-can use to create concrete \link ctfirstream CTF IR streams\endlink.
-
-A stream class has the following properties, both of which \em must
-be unique amongst all the stream classes contained in the same
-\link ctfirtraceclass CTF IR trace class\endlink:
-
-- A \b name.
-- A numeric \b ID.
-
-In the Babeltrace CTF IR system, a \link ctfirtraceclass trace class\endlink
-contains zero or more stream classes,
-and a stream class contains zero or more
-\link ctfireventclass event classes\endlink.
-You can add an event class
-to a stream class with bt_stream_class_add_event_class().
-You can add a stream class to a trace class with
-bt_trace_add_stream_class().
-
-A stream class owns three \link ctfirfieldtypes field types\endlink:
-
-- An optional <strong>stream packet context</strong> field type, which
- represents the \c stream.packet.context CTF scope.
-- An optional <strong>stream event header</strong> field type, which
- represents the \c stream.event.header CTF scope.
-- An optional <strong>stream event context</strong> field type, which
- represents the \c stream.event.context CTF scope.
-
-Those three field types \em must be structure field types as of
-Babeltrace \btversion.
-
-As per the CTF specification, the event header field type \em must
-contain a field named \c id if the stream class contains more than one
-event class.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-Before you can create a stream from a stream class with
-bt_stream_create(), you \em must add the prepared stream class to a
-trace class by calling bt_trace_add_stream_class().
-
-As with any Babeltrace object, CTF IR stream class objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-The following functions \em freeze their stream class parameter on
-success:
-
-- bt_trace_add_stream_class()
-- bt_event_create()
-- bt_writer_create_stream()
- (\link ctfwriter CTF writer\endlink mode only)
-
-You cannot modify a frozen stream class: it is considered immutable,
-except for:
-
-- Adding an event class to it with
- bt_stream_class_add_event_class(). If the stream class's parent
- \link ctfirtraceclass trace class\endlink is static, however,
- you cannot call bt_stream_class_add_event_class()
- (see bt_trace_is_static() and bt_trace_set_is_static()).
-- \link refs Reference counting\endlink.
-
-@sa ctfirstream
-@sa ctfireventclass
-@sa ctfirtraceclass
-@sa ctfwriterstreamclass
-
-@file
-@brief CTF IR stream class type and functions.
-@sa ctfirstreamclass
-
-@addtogroup ctfirstreamclass
-@{
-*/
-
-/**
-@struct bt_stream_class
-@brief A CTF IR stream class.
-@sa ctfirstreamclass
-*/
+struct bt_trace;
struct bt_stream_class;
struct bt_event_class;
-struct bt_clock;
+struct bt_clock_class;
struct bt_event_header_field;
struct bt_packet_context_field;
-/**
-@name Creation and parent access functions
-@{
-*/
-
-/**
-@brief Creates a default CTF IR stream class named \p nameÂ, or a
- default unnamed stream class if \p name is \c NULL.
-
-On success, the packet context field type of the created stream class
-has the following fields:
-
-- <code>timestamp_begin</code>: a 64-bit unsigned integer field type.
-- <code>timestamp_end</code>: a 64-bit unsigned integer field type.
-- <code>content_size</code>: a 64-bit unsigned integer field type.
-- <code>packet_size</code>: a 64-bit unsigned integer field type.
-- <code>events_discarded</code>: a 64-bit unsigned integer field type.
-
-On success, the event header field type of the created stream class
-has the following fields:
-
-- <code>code</code>: a 32-bit unsigned integer field type.
-- <code>timestamp</code>: a 64-bit unsigned integer field type.
+extern struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace);
-You can modify those default field types after the stream class is
-created with bt_stream_class_set_packet_context_field_type() and
-bt_stream_class_set_event_header_field_type().
-
-@param[in] name Name of the stream class to create (copied on success),
- or \c NULL to create an unnamed stream class.
-@returns Created default stream class, or \c NULL on error.
-
-@postsuccessrefcountret1
-
-@sa bt_stream_class_create_empty(): Creates an empty stream class.
-*/
-extern struct bt_stream_class *bt_stream_class_create(const char *name);
+extern struct bt_stream_class *bt_stream_class_create_with_id(
+ struct bt_trace *trace, uint64_t id);
extern struct bt_trace *bt_stream_class_borrow_trace(
struct bt_stream_class *stream_class);
-/**
-@brief Returns the parent CTF IR trace class of the CTF IR stream
- class \p stream_class.
-
-It is possible that the stream class was not added to a trace class
-yet, in which case this function returns \c NULL. You can add a
-stream class to a trace class with
-bt_trace_add_stream_class().
-
-@param[in] stream_class Stream class of which to get the parent
- trace class.
-@returns Parent trace class of \p stream_class,
- or \c NULL if \p stream_class was not
- added to a trace class yet or on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_add_stream_class(): Add a stream class to
- a trace class.
-*/
-static inline
-struct bt_trace *bt_stream_class_get_trace(
- struct bt_stream_class *stream_class)
-{
- return bt_get(bt_stream_class_borrow_trace(stream_class));
-}
-
-/** @} */
-
-/**
-@name Properties functions
-@{
-*/
-
-/**
-@brief Returns the name of the CTF IR stream class \p stream_class.
-
-On success, \p stream_class remains the sole owner of the returned
-string.
-
-@param[in] stream_class Stream class of which to get the name.
-@returns Name of stream class \p stream_class, or
- \c NULL if \p stream_class is unnamed or
- on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-
-@sa bt_stream_class_set_name(): Sets the name of a given
- stream class.
-*/
extern const char *bt_stream_class_get_name(
struct bt_stream_class *stream_class);
-/**
-@brief Sets the name of the CTF IR stream class
- \p stream_class to \p name, or resets the name of
- \p stream_class.
-
-If \p name is not \c NULL, it must be unique amongst the names of all
-the stream classes of the trace class to which you eventually add
-\p stream_class.
-
-@param[in] stream_class Stream class of which to set the name.
-@param[in] name Name of the stream class (copied on success), or
- \c NULL to reset the name of \p stream_class
- (make it unnamed).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{stream_class}
-@prehot{stream_class}
-@postrefcountsame{stream_class}
-
-@sa bt_stream_class_get_name(): Returns the name of a given
- stream class.
-*/
-extern int bt_stream_class_set_name(
- struct bt_stream_class *stream_class, const char *name);
-
-/**
-@brief Returns the numeric ID of the CTF IR stream class \p stream_class.
-
-@param[in] stream_class Stream class of which to get the numeric ID.
-@returns ID of stream class \p stream_class, or a
- negative value on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-
-@sa bt_stream_class_set_id(): Sets the numeric ID of a given
- stream class.
-*/
-extern int64_t bt_stream_class_get_id(
- struct bt_stream_class *stream_class);
-
-/**
-@brief Sets the numeric ID of the CTF IR stream class
- \p stream_class to \p id.
-
-\p id must be unique amongst the IDs of all the stream classes
-of the trace class to which you eventually add \p stream_class.
+extern int bt_stream_class_set_name(struct bt_stream_class *stream_class,
+ const char *name);
-@param[in] stream_class Stream class of which to set the numeric ID.
-@param[in] id ID of the stream class.
-@returns 0 on success, or a negative value on error.
+extern bt_bool bt_stream_class_assigns_automatic_event_class_id(
+ struct bt_stream_class *stream_class);
-@prenotnull{stream_class}
-@prehot{stream_class}
-@pre \p id is lesser than or equal to 9223372036854775807 (\c INT64_MAX).
-@postrefcountsame{stream_class}
+extern int bt_stream_class_set_assigns_automatic_event_class_id(
+ struct bt_stream_class *stream_class, bt_bool value);
-@sa bt_stream_class_get_id(): Returns the numeric ID of a given
- stream class.
-*/
-extern int bt_stream_class_set_id(
- struct bt_stream_class *stream_class, uint64_t id);
+extern bt_bool bt_stream_class_assigns_automatic_stream_id(
+ struct bt_stream_class *stream_class);
-/** @} */
+extern int bt_stream_class_set_assigns_automatic_stream_id(
+ struct bt_stream_class *stream_class, bt_bool value);
-/**
-@name Contained field types functions
-@{
-*/
+extern uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class);
extern struct bt_field_type *bt_stream_class_borrow_packet_context_field_type(
struct bt_stream_class *stream_class);
-/**
-@brief Returns the packet context field type of the CTF IR stream class
- \p stream_class.
-
-@param[in] stream_class Stream class of which to get the packet
- context field type.
-@returns Packet context field type of \p stream_class,
- or \c NULL if \p stream_class has no packet context
- field type or on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-@post <strong>On success, if the return value is a field type</strong>, its
- reference count is incremented.
-
-@sa bt_stream_class_set_packet_context_field_type(): Sets the packet
- context field type of a given stream class.
-*/
-static inline
-struct bt_field_type *bt_stream_class_get_packet_context_field_type(
- struct bt_stream_class *stream_class)
-{
- return bt_get(bt_stream_class_borrow_packet_context_field_type(
- stream_class));
-}
-
-extern
-struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
- struct bt_stream_class *stream_class);
-
-/**
-@brief Sets the packet context field type of the CTF IR stream class
- \p stream_class to \p packet_context_type, or unsets the current packet
- context field type from \p stream_class.
-
-If \p packet_context_type is \c NULL, then this function unsets the current
-packet context field type from \p stream_class, effectively making
-\p stream_class a stream class without a packet context field type.
-
-As of Babeltrace \btversion, if \p packet_context_type is not \c NULL,
-\p packet_context_type \em must be a CTF IR structure field type object.
-
-@param[in] stream_class Stream class of which to set the packet
- context field type.
-@param[in] packet_context_type Packet context field type, or \c NULL to unset
- the current packet context field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{stream_class}
-@prehot{stream_class}
-@pre <strong>\p packet_context_type, if not \c NULL</strong>, is a CTF IR
- structure field type.
-@postrefcountsame{stream_class}
-@post <strong>On success, if \p packet_context_type is not \c NULL</strong>,
- the reference count of \p packet_context_type is incremented.
-
-@sa bt_stream_class_get_packet_context_field_type(): Returns the packet
- context field type of a given stream class.
-*/
extern int bt_stream_class_set_packet_context_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *packet_context_type);
+ struct bt_field_type *field_type);
extern struct bt_field_type *
bt_stream_class_borrow_event_header_field_type(
struct bt_stream_class *stream_class);
-/**
-@brief Returns the event header field type of the CTF IR stream class
- \p stream_class.
-
-@param[in] stream_class Stream class of which to get the event header
- field type.
-@returns Event header field type of \p stream_class,
- or \c NULL if \p stream_class has no event header field
- type or on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-@post <strong>On success, if the return value is a field type</strong>, its
- reference count is incremented.
-
-@sa bt_stream_class_set_event_header_field_type(): Sets the event
- header field type of a given stream class.
-*/
-static inline
-struct bt_field_type *bt_stream_class_get_event_header_field_type(
- struct bt_stream_class *stream_class)
-{
- return bt_get(bt_stream_class_borrow_event_header_field_type(
- stream_class));
-}
-
-/**
-@brief Sets the event header field type of the CTF IR stream class
- \p stream_class to \p event_header_type, or unsets the current event
- header field type from \p stream_class.
-
-If \p event_header_type is \c NULL, then this function unsets the current
-event header field type from \p stream_class, effectively making \p stream_class
-a stream class without a event header field type.
-
-As of Babeltrace \btversion, if \p event_header_type is not \c NULL,
-\p event_header_type \em must be a CTF IR structure field type object.
-
-@param[in] stream_class Stream class of which to set the event
- header field type.
-@param[in] event_header_type Event header field type, or \c NULL to unset
- the current event header field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{stream_class}
-@prehot{stream_class}
-@pre <strong>\p event_header_type, if not \c NULL</strong>, is a CTF IR
- structure field type.
-@postrefcountsame{stream_class}
-@post <strong>On success, if \p event_header_type is not \c NULL</strong>,
- the reference count of \p event_header_type is incremented.
-
-@sa bt_stream_class_get_event_header_field_type(): Returns the event
- header field type of a given stream class.
-*/
extern int bt_stream_class_set_event_header_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *event_header_type);
-
-extern struct bt_event_header_field *bt_stream_class_create_event_header_field(
- struct bt_stream_class *stream_class);
+ struct bt_field_type *field_type);
extern struct bt_field_type *
-bt_stream_class_borrow_event_context_field_type(
+bt_stream_class_borrow_event_common_context_field_type(
struct bt_stream_class *stream_class);
-/**
-@brief Returns the event context field type of the CTF IR stream class
- \p stream_class.
-
-@param[in] stream_class Stream class of which to get the event context
- field type.
-@returns Event context field type of \p stream_class,
- or \c NULL if \p stream_class has no event context field
- type or on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-@post <strong>On success, if the return value is a field type</strong>,
- its reference count is incremented.
-
-
-@sa bt_stream_class_set_event_context_field_type(): Sets the event
- context field type of a given stream class.
-*/
-static inline
-struct bt_field_type *
-bt_stream_class_get_event_context_field_type(
- struct bt_stream_class *stream_class)
-{
- return bt_get(bt_stream_class_borrow_event_context_field_type(
- stream_class));
-}
-
-/**
-@brief Sets the event context field type of the CTF IR stream class
- \p stream_class to \p event_context_type, or unsets the current event
- context field type from \p stream_class.
-
-If \p event_context_type is \c NULL, then this function unsets the current
-event context field type from \p stream_class, effectively making \p
-stream_class a stream class without a event context field type.
-
-As of Babeltrace \btversion, if \p event_context_type is not \c NULL,
-\p event_context_type \em must be a CTF IR structure field type object.
-
-@param[in] stream_class Stream class of which to set the packet
- context field type.
-@param[in] event_context_type Event context field type, or \c NULL to unset
- the current event context field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{stream_class}
-@prehot{stream_class}
-@pre <strong>\p event_context_type, if not \c NULL</strong>, is a CTF IR
- structure field type.
-@postrefcountsame{stream_class}
-@post <strong>On success, if \p event_context_type is not \c NULL</strong>,
- the reference count of \p event_context_type is incremented.
-
-@sa bt_stream_class_get_event_context_field_type(): Returns the event context
- field type of a given stream class.
-*/
-extern int bt_stream_class_set_event_context_field_type(
+extern int bt_stream_class_set_event_common_context_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *event_context_type);
-
-/** @} */
-
-/**
-@name Event class children functions
-@{
-*/
-
-/**
-@brief Returns the number of event classes contained in the
- CTF IR stream class \p stream_class.
+ struct bt_field_type *field_type);
-@param[in] stream_class Stream class of which to get the number
- of children event classes.
-@returns Number of children event classes
- contained in \p stream_class, or
- a negative value on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-*/
-extern int64_t bt_stream_class_get_event_class_count(
+extern uint64_t bt_stream_class_get_event_class_count(
struct bt_stream_class *stream_class);
extern struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
struct bt_stream_class *stream_class, uint64_t index);
-/**
-@brief Returns the event class at index \p index in the CTF IR stream
- class \p stream_class.
-
-@param[in] stream_class Stream class of which to get the event class.
-@param[in] index Index of the event class to find.
-@returns Event class at index \p index, or \c NULL
- on error.
-
-@prenotnull{stream_class}
-@pre \p index is lesser than the number of event classes contained in the
- stream class \p stream_class (see
- bt_stream_class_get_event_class_count()).
-@postrefcountsame{stream_class}
-@postsuccessrefcountretinc
-
-@sa bt_stream_class_get_event_class_by_id(): Finds an event class
- by ID.
-*/
-static inline
-struct bt_event_class *bt_stream_class_get_event_class_by_index(
- struct bt_stream_class *stream_class, uint64_t index)
-{
- return bt_get(bt_stream_class_borrow_event_class_by_index(stream_class,
- index));
-}
-
extern struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
struct bt_stream_class *stream_class, uint64_t id);
-/**
-@brief Returns the event class with ID \c id found in the CTF IR stream
- class \p stream_class.
-
-@param[in] stream_class Stream class of which to get the event class.
-@param[in] id ID of the event class to find.
-@returns Event class with ID \p id, or \c NULL
- on error.
-
-@prenotnull{stream_class}
-@postrefcountsame{stream_class}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_event_class *bt_stream_class_get_event_class_by_id(
- struct bt_stream_class *stream_class, uint64_t id)
-{
- return bt_get(bt_stream_class_borrow_event_class_by_id(stream_class,
- id));
-}
-
-/**
-@brief Adds the CTF IR event class \p event_class to the
- CTF IR stream class \p stream_class.
-
-On success, \p event_class becomes the child of \p stream_class.
-
-You can only add a given event class to one stream class.
-
-You can call this function even if \p stream_class is frozen. Adding
-event classes is the only operation that is permitted
-on a frozen stream class.
-
-This function tries to resolve the needed
-\link ctfirfieldtypes CTF IR field type\endlink of the dynamic field
-types that are found anywhere in the context or payload field
-types of \p event_class. If any automatic resolving fails:
-
-- If the needed field type should be found in one of the root field
- types of \p event_class or \p stream_class, this function fails.
-- If \p stream_class is the child of a
- \link ctfirtraceclass CTF IR trace class\endlink (it was added
- with bt_trace_add_stream_class()), this function fails.
-- If \p stream_class is not the child of a trace class yet, the
- automatic resolving is reported to the next call to
- bt_trace_add_stream_class() with \p stream_class.
-
-@param[in] stream_class Stream class to which to add \p event_class.
-@param[in] event_class Event class to add to \p stream_class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{stream_class}
-@prenotnull{event_class}
-@prehot{event_class}
-@postrefcountsame{stream_class}
-@postsuccessrefcountinc{event_class}
-@postsuccessfrozen{event_class}
-*/
-extern int bt_stream_class_add_event_class(
+extern int bt_stream_class_set_default_clock_class(
struct bt_stream_class *stream_class,
- struct bt_event_class *event_class);
+ struct bt_clock_class *clock_class);
+
+extern struct bt_clock_class *bt_stream_class_borrow_default_clock_class(
+ struct bt_stream_class *stream_class);
-/** @} */
+extern bt_bool bt_stream_class_default_clock_is_always_known(
+ struct bt_stream_class *stream_class);
-/**
-@name Misc. function
-@{
-*/
+extern bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot(
+ struct bt_stream_class *stream_class);
-/**
-@brief Accepts the visitor \p visitor to visit the hierarchy of the
- CTF IR stream class \p stream_class.
+extern int bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
+ struct bt_stream_class *stream_class, bt_bool value);
-This function traverses the hierarchy of \p stream_class in pre-order
-and calls \p visitor on each element.
+extern bt_bool bt_stream_class_packets_have_packet_counter_snapshot(
+ struct bt_stream_class *stream_class);
-The stream class itself is visited first, and then all its children
-event classes.
+extern int bt_stream_class_set_packets_have_packet_counter_snapshot(
+ struct bt_stream_class *stream_class, bt_bool value);
-@param[in] stream_class Stream class to visit.
-@param[in] visitor Visiting function.
-@param[in] data User data.
-@returns 0 on success, or a negative value on error.
+extern bt_bool bt_stream_class_packets_have_default_beginning_clock_value(
+ struct bt_stream_class *stream_class);
-@prenotnull{stream_class}
-@prenotnull{visitor}
-*/
-extern int bt_stream_class_visit(struct bt_stream_class *stream_class,
- bt_visitor visitor, void *data);
+extern int bt_stream_class_set_packets_have_default_beginning_clock_value(
+ struct bt_stream_class *stream_class, bt_bool value);
-/** @} */
+extern bt_bool bt_stream_class_packets_have_default_end_clock_value(
+ struct bt_stream_class *stream_class);
-/** @} */
+extern int bt_stream_class_set_packets_have_default_end_clock_value(
+ struct bt_stream_class *stream_class, bt_bool value);
#ifdef __cplusplus
}
* SOFTWARE.
*/
-#include <babeltrace/assert-pre-internal.h>
-#include <babeltrace/assert-internal.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/object-internal.h>
struct bt_stream {
struct bt_object base;
- int64_t id;
- struct bt_stream_class *stream_class;
- GString *name;
+
+ /* Weak: parent is this class's trace */
+ struct bt_stream_class *class;
+
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } name;
+
+ uint64_t id;
/* Pool of `struct bt_packet *` */
struct bt_object_pool packet_pool;
+
+ bool frozen;
};
+BT_HIDDEN
+void _bt_stream_freeze(struct bt_stream *stream);
+
+#ifdef BT_DEV_MODE
+# define bt_stream_freeze _bt_stream_freeze
+#else
+# define bt_stream_freeze(_stream)
+#endif
+
#endif /* BABELTRACE_CTF_IR_STREAM_INTERNAL_H */
* http://www.efficios.com/ctf
*/
-/* For bt_get() */
-#include <babeltrace/ref.h>
+/* For enum bt_property_availability */
+#include <babeltrace/property.h>
#include <stdint.h>
extern "C" {
#endif
-struct bt_stream_class;
-
-/**
-@defgroup ctfirstream CTF IR stream
-@ingroup ctfir
-@brief CTF IR stream.
-
-@code
-#include <babeltrace/ctf-ir/stream.h>
-@endcode
-
-@note
-See \ref ctfwriterstream which documents additional CTF IR stream
-functions exclusive to the CTF writer mode.
-
-A CTF IR <strong><em>stream</em></strong> is an instance of a
-\link ctfirstreamclass CTF IR stream class\endlink.
-
-You can obtain a CTF IR stream object in two different modes:
-
-- <strong>Normal mode</strong>: use bt_stream_create() or
- bt_stream_create_with_id() with a stream class having a
- \link ctfirtraceclass CTF IR trace class\endlink parent
- \em not created by a \link ctfwriter CTF writer\endlink object to
- create a default stream.
-- <strong>CTF writer mode</strong>: use bt_stream_create() with
- a stream class having a trace class parent created by a CTF writer
- object, or use bt_writer_create_stream().
-
-A CTF IR stream object represents a CTF stream, that is, a sequence of
-packets containing events:
-
-@imgtracestructure
-
-A CTF IR stream does not contain, however, actual \link ctfirpacket CTF
-IR packet\endlink objects: it only acts as a common parent to identify
-the original CTF stream of packet objects.
-
-As with any Babeltrace object, CTF IR stream objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-@sa ctfirstreamclass
-@sa ctfirpacket
-@sa ctfwriterstream
-
-@file
-@brief CTF IR stream type and functions.
-@sa ctfirstream
-
-@addtogroup ctfirstream
-@{
-*/
-
-/**
-@struct bt_stream
-@brief A CTF IR stream.
-@sa ctfirstream
-@sa ctfwriterstream
-*/
struct bt_stream;
-struct bt_event;
-
-/**
-@brief Creates a default CTF IR stream named \p name with ID \p id
- from the CTF IR stream class \p stream_class.
-
-\p stream_class \em must have a parent
-\link ctfirtraceclass CTF IR trace class\endlink.
-
-\p id \em must be unique amongst the IDs of all the streams created
-from \p stream_class with bt_stream_create_with_id().
-
-\p name can be \c NULL to create an unnamed stream object.
-
-@param[in] stream_class CTF IR stream class to use to create the
- CTF IR stream.
-@param[in] name Name of the stream object to create (copied on
- success) or \c NULL to create an unnamed stream.
-@param[in] id ID of the stream object to create.
-@returns Created stream object, or \c NULL on error.
-
-@prenotnull{stream_class}
-@pre \p id is lesser than or equal to 9223372036854775807 (\c INT64_MAX).
-@pre \p stream_class has a parent trace class.
-@postsuccessrefcountret1
-*/
-extern struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
- const char *name, uint64_t id);
+struct bt_stream_class;
-/**
-@brief Returns the name of the CTF IR stream \p stream.
+extern struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class);
-On success, \p stream remains the sole owner of the returned string.
+extern struct bt_stream *bt_stream_create_with_id(
+ struct bt_stream_class *stream_class, uint64_t id);
-@param[in] stream Stream object of which to get the name.
-@returns Name of stream \p stream, or \c NULL if
- \p stream is unnamed or on error.
+extern struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream);
-@prenotnull{stream}
-@postrefcountsame{stream}
-*/
extern const char *bt_stream_get_name(struct bt_stream *stream);
-/**
-@brief Returns the numeric ID of the CTF IR stream \p stream.
-
-@param[in] stream Stream of which to get the numeric ID.
-@returns ID of stream \p stream, or a negative value
- on error.
-
-@prenotnull{stream}
-@postrefcountsame{stream}
-*/
-extern int64_t bt_stream_get_id(struct bt_stream *stream);
-
-extern struct bt_stream_class *bt_stream_borrow_class(
- struct bt_stream *stream);
-
-/**
-@brief Returns the parent CTF IR stream class of the CTF IR
- stream \p stream.
-
-This function returns a reference to the stream class which was used
-to create the stream object in the first place with
-bt_stream_create().
-
-@param[in] stream Stream of which to get the parent stream class.
-@returns Parent stream class of \p stream,
- or \c NULL on error.
-
-@prenotnull{stream}
-@postrefcountsame{stream}
-@postsuccessrefcountretinc
-*/
-static inline
-struct bt_stream_class *bt_stream_get_class(
- struct bt_stream *stream)
-{
- return bt_get(bt_stream_borrow_class(stream));
-}
+extern int bt_stream_set_name(struct bt_stream *stream, const char *name);
-/** @} */
+extern uint64_t bt_stream_get_id(struct bt_stream *stream);
#ifdef __cplusplus
}
#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/field-types.h>
#include <babeltrace/ctf-ir/fields.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/ctf-ir/attributes-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/object-internal.h>
struct bt_trace {
struct bt_object base;
- GString *name;
- int frozen;
- unsigned char uuid[BABELTRACE_UUID_LEN];
- bt_bool uuid_set;
- enum bt_byte_order native_byte_order;
+
+ struct {
+ GString *str;
+
+ /* NULL or `str->str` above */
+ const char *value;
+ } name;
+
+ struct {
+ uint8_t uuid[BABELTRACE_UUID_LEN];
+
+ /* NULL or `uuid` above */
+ bt_uuid value;
+ } uuid;
+
struct bt_value *environment;
- GPtrArray *clock_classes; /* Array of pointers to bt_clock_class */
- GPtrArray *stream_classes; /* Array of ptrs to bt_stream_class */
- GPtrArray *streams; /* Array of ptrs to bt_stream */
- struct bt_field_type *packet_header_field_type;
- int64_t next_stream_id;
+
+ /* Array of `struct bt_stream_class *` */
+ GPtrArray *stream_classes;
+
+ /* Array of `struct bt_stream *` */
+ GPtrArray *streams;
/*
- * This flag indicates if the trace is valid. A valid
- * trace is _always_ frozen.
+ * Stream class (weak) to number of instantiated streams, used
+ * to automatically assign stream IDs per stream class.
*/
- int valid;
+ GHashTable *stream_classes_stream_count;
+
+ struct bt_field_type *packet_header_ft;
+ bool assigns_automatic_stream_class_id;
- GPtrArray *listeners; /* Array of struct listener_wrapper */
GArray *is_static_listeners;
- bt_bool is_static;
- bt_bool in_remove_listener;
+ bool is_static;
+ bool in_remove_listener;
/* Pool of `struct bt_field_wrapper *` */
struct bt_object_pool packet_header_field_pool;
-};
-BT_HIDDEN
-int bt_trace_object_modification(struct bt_visitor_object *object,
- void *trace_ptr);
+ bool frozen;
+};
BT_HIDDEN
-bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
- struct bt_clock_class *clock_class);
-
-/**
-@brief User function type to use with bt_trace_add_listener().
+void _bt_trace_freeze(struct bt_trace *trace);
-@param[in] obj New CTF IR object which is part of the trace
- class hierarchy.
-@param[in] data User data.
+#ifdef BT_DEV_MODE
+# define bt_trace_freeze _bt_trace_freeze
+#else
+# define bt_trace_freeze(_trace)
+#endif
-@prenotnull{obj}
-*/
-typedef void (*bt_listener_cb)(struct bt_visitor_object *obj, void *data);
-
-/**
-@brief Adds the trace class modification listener \p listener to
- the CTF IR trace class \p trace_class.
-
-Once you add \p listener to \p trace_class, whenever \p trace_class
-is modified, \p listener is called with the new element and with
-\p data (user data).
-
-@param[in] trace_class Trace class to which to add \p listener.
-@param[in] listener Modification listener function.
-@param[in] data User data.
-@returns 0 on success, or a negative value on error.
+BT_HIDDEN
+void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream);
-@prenotnull{trace_class}
-@prenotnull{listener}
-@postrefcountsame{trace_class}
-*/
BT_HIDDEN
-int bt_trace_add_listener(struct bt_trace *trace_class,
- bt_listener_cb listener, void *data);
-
-static inline
-void bt_trace_freeze(struct bt_trace *trace)
-{
- int i;
-
- if (trace->frozen) {
- return;
- }
-
- BT_LOGD("Freezing trace: addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
- BT_LOGD_STR("Freezing packet header field type.");
- bt_field_type_freeze(trace->packet_header_field_type);
- BT_LOGD_STR("Freezing environment attributes.");
- bt_attributes_freeze(trace->environment);
-
- if (trace->clock_classes->len > 0) {
- BT_LOGD_STR("Freezing clock classes.");
- }
-
- for (i = 0; i < trace->clock_classes->len; i++) {
- struct bt_clock_class *clock_class =
- g_ptr_array_index(trace->clock_classes, i);
-
- bt_clock_class_freeze(clock_class);
- }
-
- trace->frozen = 1;
-}
+uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace,
+ struct bt_stream_class *stream_class);
#endif /* BABELTRACE_CTF_IR_TRACE_INTERNAL_H */
* http://www.efficios.com/ctf
*/
-/* For bt_get() */
-#include <babeltrace/ref.h>
-
-/* For bt_visitor */
-#include <babeltrace/ctf-ir/visitor.h>
-
-/* For bt_bool */
+/* For bt_bool, bt_uuid */
#include <babeltrace/types.h>
+
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
-/**
-@defgroup ctfirtraceclass CTF IR trace class
-@ingroup ctfir
-@brief CTF IR trace class.
-
-@code
-#include <babeltrace/ctf-ir/trace.h>
-@endcode
-
-A CTF IR <strong><em>trace class</em></strong> is a descriptor of
-traces.
-
-You can obtain a trace class in two different modes:
-
-- <strong>Normal mode</strong>: use bt_trace_create() to create a
- default, empty trace class.
-- <strong>CTF writer mode</strong>: use bt_writer_get_trace() to
- get the trace class created by a given CTF writer object.
-
-A trace class has the following properties:
-
-- A \b name.
-- A <strong>native byte order</strong>: all the
- \link ctfirfieldtypes field types\endlink eventually part of the trace
- class with a byte order set to #BT_BYTE_ORDER_NATIVE have this
- "real" byte order.
-- A \b UUID.
-- An \b environment, which is a custom key-value mapping. Keys are
- strings and values can be strings or integers.
-
-In the Babeltrace CTF IR system, a trace class contains zero or more
-\link ctfirstreamclass stream classes\endlink, and a stream class
-contains zero or more \link ctfireventclass event classes\endlink. You
-can add an event class to a stream class with
-bt_stream_class_add_event_class(). You can add a stream class to a
-trace class with bt_trace_add_stream_class().
-
-You can access the streams of a trace, that is, the streams which were
-created from the trace's stream classes with bt_stream_create(),
-with bt_trace_get_stream_by_index().
-
-A trace class owns the <strong>trace packet header</strong>
-\link ctfirfieldtypes field type\endlink, which represents the
-\c trace.packet.header CTF scope. This field type describes the
-trace packet header fields of the traces that this trace class
-describes.
-
-The trace packet header field type \em must be a structure field type as
-of Babeltrace \btversion.
-
-As per the CTF specification, the trace packet header field type \em
-must contain a field named \c stream_id if the trace class contains more
-than one stream class.
-
-As a reminder, here's the structure of a CTF packet:
-
-@imgpacketstructure
-
-A trace class also contains zero or more
-\link ctfirclockclass CTF IR clock classes\endlink.
-
-@todo
-Elaborate about clock classes irt clock values.
-
-As with any Babeltrace object, CTF IR trace class objects have
-<a href="https://en.wikipedia.org/wiki/Reference_counting">reference
-counts</a>. See \ref refs to learn more about the reference counting
-management of Babeltrace objects.
-
-The following functions \em freeze their trace class parameter on
-success:
-
-- bt_trace_add_stream_class()
-- bt_writer_create_stream()
- (\link ctfwriter CTF writer\endlink mode only)
-
-You cannot modify a frozen trace class: it is considered immutable,
-except for:
-
-- Adding a stream class to it with
- bt_trace_add_stream_class().
-- Adding a CTF IR clock class to it with bt_trace_add_clock_class().
-- \link refs Reference counting\endlink.
-
-@sa ctfirstreamclass
-@sa ctfireventclass
-@sa ctfirclockclass
-
-@file
-@brief CTF IR trace class type and functions.
-@sa ctfirtraceclass
-
-@addtogroup ctfirtraceclass
-@{
-*/
-
-/**
-@struct bt_trace
-@brief A CTF IR trace class.
-@sa ctfirtraceclass
-*/
struct bt_trace;
struct bt_stream;
struct bt_stream_class;
-struct bt_clock_class;
struct bt_field_type;
struct bt_value;
struct bt_packet_header_field;
-/**
-@brief User function type to use with
- bt_trace_add_is_static_listener().
-
-@param[in] trace_class Trace class which is now static.
-@param[in] data User data as passed to
- bt_trace_add_is_static_listener() when
- you added the listener.
-
-@prenotnull{trace_class}
-*/
typedef void (* bt_trace_is_static_listener)(
- struct bt_trace *trace_class, void *data);
-
-/**
-@brief User function type to use with
- bt_trace_add_is_static_listener().
+ struct bt_trace *trace, void *data);
-@param[in] trace_class Trace class to which the listener was added.
-@param[in] data User data as passed to
- bt_trace_add_is_static_listener() when
- you added the listener.
-
-@prenotnull{trace_class}
-*/
typedef void (* bt_trace_listener_removed)(
- struct bt_trace *trace_class, void *data);
-
-/**
-@name Creation function
-@{
-*/
-
-/**
-@brief Creates a default CTF IR trace class.
-
-On success, the trace packet header field type of the created trace
-class is an empty structure field type. You can modify this default
-trace packet header field type after the trace class is created with
-bt_trace_get_packet_header_field_type() and
-bt_trace_set_packet_header_field_type().
-
-The created trace class has the following initial properties:
-
-- <strong>Name</strong>: none. You can set a name
- with bt_trace_set_name().
-- <strong>UUID</strong>: none. You can set a UUID with
- bt_trace_set_uuid().
-- <strong>Native byte order</strong>: #BT_BYTE_ORDER_UNSPECIFIED.
- You can set a native byte order with
- bt_trace_set_native_byte_order().
-- <strong>Environment</strong>: empty. You can add environment entries
- with bt_trace_set_environment_field(),
- bt_trace_set_environment_field_integer(), and
- bt_trace_set_environment_field_string().
+ struct bt_trace *trace, void *data);
-@returns Created trace class, or \c NULL on error.
-
-@postsuccessrefcountret1
-*/
extern struct bt_trace *bt_trace_create(void);
-/** @} */
-
-/**
-@name Properties functions
-@{
-*/
-
-/**
-@brief Returns the name of the CTF IR trace class \p trace_class.
-
-On success, \p trace_class remains the sole owner of the returned
-string. The returned string is valid as long as \p trace_class exists
-and is not modified.
-
-@param[in] trace_class Trace class of which to get the name.
-@returns Name of trace class \p trace_class, or
- \c NULL if \p trace_class is unnamed or
- on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-
-@sa bt_trace_set_name(): Sets the name of a given trace class.
-*/
-extern const char *bt_trace_get_name(struct bt_trace *trace_class);
-
-/**
-@brief Sets the name of the CTF IR trace class \p trace_class
- to \p name.
-
-@param[in] trace_class Trace class of which to set the name.
-@param[in] name Name of the trace class (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{name}
-@prehot{trace_class}
-@postrefcountsame{trace_class}
-
-@sa bt_trace_get_name(): Returns the name of a given trace class.
-*/
-extern int bt_trace_set_name(struct bt_trace *trace_class,
- const char *name);
-
-/**
-@brief Returns the native byte order of the CTF IR trace class
- \p trace_class.
-
-@param[in] trace_class Trace class of which to get the default byte
- order.
-@returns Native byte order of \p trace_class,
- or #BT_BYTE_ORDER_UNKNOWN on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-
-@sa bt_trace_set_native_byte_order(): Sets the native byte order of
- a given trace class.
-*/
-extern enum bt_byte_order bt_trace_get_native_byte_order(
- struct bt_trace *trace_class);
-
-/**
-@brief Sets the native byte order of the CTF IR trace class
- \p trace_class to \p native_byte_order.
-
-\p native_byte_order \em must be one of:
-
-- #BT_BYTE_ORDER_LITTLE_ENDIAN
-- #BT_BYTE_ORDER_BIG_ENDIAN
-- #BT_BYTE_ORDER_NETWORK
-- <strong>If the trace is not in CTF writer mode<strong>,
- #BT_BYTE_ORDER_UNSPECIFIED.
-
-@param[in] trace_class Trace class of which to set the native byte
- order.
-@param[in] native_byte_order Native byte order of the trace class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prehot{trace_class}
-@pre \p native_byte_order is either #BT_BYTE_ORDER_UNSPECIFIED (if the
- trace is not in CTF writer mode),
- #BT_BYTE_ORDER_LITTLE_ENDIAN, #BT_BYTE_ORDER_BIG_ENDIAN, or
- #BT_BYTE_ORDER_NETWORK.
-@postrefcountsame{trace_class}
-
-@sa bt_trace_get_native_byte_order(): Returns the native byte order of a
- given trace class.
-*/
-extern int bt_trace_set_native_byte_order(struct bt_trace *trace_class,
- enum bt_byte_order native_byte_order);
-
-/**
-@brief Returns the UUID of the CTF IR trace class \p trace_class.
-
-On success, the return value is an array of 16 bytes.
-
-@param[in] trace_class Trace class of which to get the UUID.
-@returns UUID of trace class \p trace_class, or
- \c NULL if \p trace_class has no UUID or on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-
-@sa bt_trace_set_uuid(): Sets the UUID of a given trace class.
-*/
-extern const unsigned char *bt_trace_get_uuid(
- struct bt_trace *trace_class);
-
-/**
-@brief Sets the UUID of the CTF IR trace class \p trace_class to
- \p uuid.
-
-\p uuid \em must be an array of 16 bytes.
-
-@param[in] trace_class Trace class of which to set the UUID.
-@param[in] uuid UUID of the \p trace_class (copied on
- success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{uuid}
-@prehot{trace_class}
-@pre \p uuid is an array of 16 bytes.
-@postrefcountsame{trace_class}
-
-@sa bt_trace_get_uuid(): Returns the UUID of a given trace class.
-*/
-extern int bt_trace_set_uuid(struct bt_trace *trace_class,
- const unsigned char *uuid);
-
-/**
-@brief Returns the number of entries contained in the environment of
- the CTF IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the number
- of environment entries.
-@returns Number of environment entries
- contained in \p trace_class, or
- a negative value on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-*/
-extern int64_t bt_trace_get_environment_field_count(
- struct bt_trace *trace_class);
-
-/**
-@brief Returns the field name of the environment entry at index
- \p index in the CTF IR trace class \p trace_class.
-
-On success, the returned string is valid as long as this trace class
-exists and is \em not modified. \p trace_class remains the sole owner of
-the returned string.
-
-@param[in] trace_class Trace class of which to get the name of the
- environment entry at index \p index.
-@param[in] index Index of environment entry to find.
-@returns Name of the environment entry at index \p index
- in \p trace_class, or \c NULL on error.
-
-@prenotnull{trace_class}
-@pre \p index is lesser than the number of environment entries in
- \p trace_class (see bt_trace_get_environment_field_count()).
-@postrefcountsame{trace_class}
-
-@sa bt_trace_get_environment_field_value_by_index(): Finds a trace class's
- environment entry by index.
-@sa bt_trace_get_environment_field_value_by_name(): Finds a trace
- class's environment entry by name.
-@sa bt_trace_set_environment_field(): Sets the value of a trace
- class's environment entry.
-*/
-extern const char *
-bt_trace_get_environment_field_name_by_index(
- struct bt_trace *trace_class, uint64_t index);
-
-extern struct bt_value *
-bt_trace_borrow_environment_field_value_by_index(struct bt_trace *trace_class,
- uint64_t index);
-
-/**
-@brief Returns the value of the environment entry at index
- \p index in the CTF IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the value of the
- environment entry at index \p index.
-@param[in] index Index of the environment entry to find.
-@returns Value of the environment entry at index \p index
- in \p trace_class, or \c NULL on error.
-
-@prenotnull{trace_class}
-@pre \p index is lesser than the number of environment entries in
- \p trace_class (see bt_trace_get_environment_field_count()).
-@postrefcountsame{trace_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_get_environment_field_value_by_name(): Finds a trace
- class's environment entry by name.
-@sa bt_trace_set_environment_field(): Sets the value of a trace
- class's environment entry.
-*/
-static inline
-struct bt_value *bt_trace_get_environment_field_value_by_index(
- struct bt_trace *trace_class, uint64_t index)
-{
- return bt_get(bt_trace_borrow_environment_field_value_by_index(
- trace_class, index));
-}
-
-extern struct bt_value *
-bt_trace_borrow_environment_field_value_by_name(
- struct bt_trace *trace_class, const char *name);
-
-/**
-@brief Returns the value of the environment entry named \p name
- in the CTF IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the value of the
- environment entry named \p name.
-@param[in] name Name of the environment entry to find.
-@returns Value of the environment entry named \p name
- in \p trace_class, or \c NULL if there's no such
- entry or on error.
-
-@prenotnull{trace_class}
-@prenotnull{name}
-@postrefcountsame{trace_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_get_environment_field_value_by_index(): Finds a trace class's
- environment entry by index.
-@sa bt_trace_set_environment_field(): Sets the value of a trace
- class's environment entry.
-*/
-static inline
-struct bt_value *
-bt_trace_get_environment_field_value_by_name(
- struct bt_trace *trace_class, const char *name)
-{
- return bt_get(
- bt_trace_borrow_environment_field_value_by_name(
- trace_class, name));
-}
-
-/**
-@brief Sets the environment entry named \p name in the
- CTF IR trace class \p trace_class to \p value.
+extern bt_bool bt_trace_assigns_automatic_stream_class_id(
+ struct bt_trace *trace);
-If an environment entry named \p name exists in \p trace_class, its
-value is first put, and then replaced by \p value.
+extern int bt_trace_set_assigns_automatic_stream_class_id(
+ struct bt_trace *trace, bt_bool value);
-@param[in] trace_class Trace class of which to set the environment
- entry.
-@param[in] name Name of the environment entry to set (copied
- on success).
-@param[in] value Value of the environment entry named \p name.
-@returns 0 on success, or a negative value on error.
+extern const char *bt_trace_get_name(struct bt_trace *trace);
-@prenotnull{trace_class}
-@prenotnull{name}
-@prenotnull{value}
-@prehot{trace_class}
-@pre \p value is an
- \link bt_value_integer_create() integer value object\endlink
- or a
- \link bt_value_string_create() string value object\endlink.
-@postrefcountsame{trace_class}
-@postsuccessrefcountinc{value}
+extern int bt_trace_set_name(struct bt_trace *trace, const char *name);
-@sa bt_trace_get_environment_field_value_by_index(): Finds a trace class's
- environment entry by index.
-@sa bt_trace_get_environment_field_value_by_name(): Finds a trace
- class's environment entry by name.
-*/
-extern int bt_trace_set_environment_field(
- struct bt_trace *trace_class, const char *name,
- struct bt_value *value);
+extern bt_uuid bt_trace_get_uuid(struct bt_trace *trace);
-/**
-@brief Sets the environment entry named \p name in the
- CTF IR trace class \p trace_class to \p value.
+extern int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid uuid);
-If an environment entry named \p name exists in \p trace_class, its
-value is first put, and then replaced by a new
-\link bt_value_integer_create() integer value object\endlink
-containing \p value.
+extern uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace);
-@param[in] trace_class Trace class of which to set the environment
- entry.
-@param[in] name Name of the environment entry to set (copied
- on success).
-@param[in] value Value of the environment entry named \p name.
-@returns 0 on success, or a negative value on error.
+extern void bt_trace_borrow_environment_entry_by_index(
+ struct bt_trace *trace, uint64_t index,
+ const char **name, struct bt_value **value);
-@prenotnull{trace_class}
-@prenotnull{name}
-@prehot{trace_class}
-@postrefcountsame{trace_class}
+extern struct bt_value *bt_trace_borrow_environment_entry_value_by_name(
+ struct bt_trace *trace, const char *name);
-@sa bt_trace_set_environment_field(): Sets the value of a trace
- class's environment entry.
-*/
-extern int bt_trace_set_environment_field_integer(
- struct bt_trace *trace_class, const char *name,
+extern int bt_trace_set_environment_entry_integer(
+ struct bt_trace *trace, const char *name,
int64_t value);
-/**
-@brief Sets the environment entry named \p name in the
- CTF IR trace class \p trace_class to \p value.
-
-If an environment entry named \p name exists in \p trace_class, its
-value is first put, and then replaced by a new
-\link bt_value_string_create() string value object\endlink
-containing \p value.
-
-@param[in] trace_class Trace class of which to set the environment
- entry.
-@param[in] name Name of the environment entry to set (copied
- on success).
-@param[in] value Value of the environment entry named \p name
- (copied on success).
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{name}
-@prenotnull{value}
-@prehot{trace_class}
-@postrefcountsame{trace_class}
-
-@sa bt_trace_set_environment_field(): Sets the value of a trace
- class's environment entry.
-*/
-extern int bt_trace_set_environment_field_string(
- struct bt_trace *trace_class, const char *name,
+extern int bt_trace_set_environment_entry_string(
+ struct bt_trace *trace, const char *name,
const char *value);
-/** @} */
-
-/**
-@name Contained field types functions
-@{
-*/
-
extern struct bt_field_type *bt_trace_borrow_packet_header_field_type(
- struct bt_trace *trace_class);
-
-/**
-@brief Returns the packet header field type of the CTF IR trace class
- \p trace_class.
-
-@param[in] trace_class Trace class of which to get the packet
- header field type.
-@returns Packet header field type of \p trace_class,
- or \c NULL if \p trace_class has no packet header field
- type or on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-@post <strong>On success, if the return value is a field type</strong>, its
- reference count is incremented.
-
-@sa bt_trace_set_packet_header_field_type(): Sets the packet
- header field type of a given trace class.
-*/
-static inline
-struct bt_field_type *bt_trace_get_packet_header_field_type(
- struct bt_trace *trace_class)
-{
- return bt_get(bt_trace_borrow_packet_header_field_type(trace_class));
-}
-
-extern struct bt_packet_header_field *bt_trace_create_packet_header_field(
struct bt_trace *trace);
-/**
-@brief Sets the packet header field type of the CTF IR trace class
- \p trace_class to \p packet_header_type, or unsets the current packet
- header field type from \p trace_class.
-
-If \p packet_header_type is \c NULL, then this function unsets the current
-packet header field type from \p trace_class, effectively making \p trace_class
-a trace without a packet header field type.
-
-As of Babeltrace \btversion, if \p packet_header_type is not \c NULL,
-\p packet_header_type \em must be a CTF IR structure field type object.
-
-@param[in] trace_class Trace class of which to set the packet
- header field type.
-@param[in] packet_header_type Packet header field type, or \c NULL to unset
- the current packet header field type.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prehot{trace_class}
-@pre <strong>\p packet_header_type, if not \c NULL</strong>, is a CTF IR
- structure field type.
-@postrefcountsame{trace_class}
-@post <strong>On success, if \p packet_header_type is not \c NULL</strong>,
- the reference count of \p packet_header_type is incremented.
-
-@sa bt_trace_get_packet_header_field_type(): Returns the packet
- header field type of a given trace class.
-*/
-extern int bt_trace_set_packet_header_field_type(struct bt_trace *trace_class,
+extern int bt_trace_set_packet_header_field_type(struct bt_trace *trace,
struct bt_field_type *packet_header_type);
-/** @} */
-
-/**
-@name Contained clock classes functions
-@{
-*/
-
-/**
-@brief Returns the number of CTF IR clock classes contained in the
- CTF IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the number
- of contained clock classes.
-@returns Number of contained clock classes
- contained in \p trace_class, or a negative
- value on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-*/
-extern int64_t bt_trace_get_clock_class_count(
- struct bt_trace *trace_class);
-
-extern struct bt_clock_class *bt_trace_borrow_clock_class_by_index(
- struct bt_trace *trace_class, uint64_t index);
-
-/**
-@brief Returns the CTF IR clock class at index \p index in the CTF
- IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the clock class
- contained at index \p index.
-@param[in] index Index of the clock class to find in
- \p trace_class.
-@returns Clock class at index \p index in \p trace_class,
- or \c NULL on error.
-
-@prenotnull{trace_class}
-@pre \p index is lesser than the number of clock classes contained in
- the trace class \p trace_class (see
- bt_trace_get_clock_class_count()).
-@postrefcountsame{trace_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_get_clock_class_by_name(): Finds a clock class by name
- in a given trace class.
-@sa bt_trace_add_clock_class(): Adds a clock class to a trace class.
-*/
-static inline
-struct bt_clock_class *bt_trace_get_clock_class_by_index(
- struct bt_trace *trace_class, uint64_t index)
-{
- return bt_get(bt_trace_borrow_clock_class_by_index(
- trace_class, index));
-}
-
-extern struct bt_clock_class *bt_trace_borrow_clock_class_by_name(
- struct bt_trace *trace_class, const char *name);
-
-/**
-@brief Returns the CTF IR clock class named \c name found in the CTF
- IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the clock class
- named \p name.
-@param[in] name Name of the clock class to find in \p trace_class.
-@returns Clock class named \p name in \p trace_class,
- or \c NULL on error.
-
-@prenotnull{trace_class}
-@prenotnull{name}
-@postrefcountsame{trace_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_get_clock_class_by_index(): Returns the clock class contained
- in a given trace class at a given index.
-@sa bt_trace_add_clock_class(): Adds a clock class to a trace class.
-*/
-static inline
-struct bt_clock_class *bt_trace_get_clock_class_by_name(
- struct bt_trace *trace_class, const char *name)
-{
- return bt_get(bt_trace_borrow_clock_class_by_name(trace_class, name));
-}
-
-/**
-@brief Adds the CTF IR clock class \p clock_class to the CTF IR
- trace class \p trace_class.
-
-On success, \p trace_class contains \p clock_class.
-
-You can call this function even if \p trace_class or \p clock_class
-are frozen.
-
-@param[in] trace_class Trace class to which to add \p clock_class.
-@param[in] clock_class Clock class to add to \p trace_class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{clock_class}
-@postrefcountsame{trace_class}
-@postsuccessrefcountinc{clock_class}
-@post <strong>On success, if \p trace_class is frozen</strong>,
- \p clock_class is frozen.
-
-@sa bt_trace_get_clock_class_by_index(): Returns the clock class contained
- in a given trace class at a given index.
-@sa bt_trace_get_clock_class_by_name(): Finds a clock class by name
- in a given trace class.
-*/
-extern int bt_trace_add_clock_class(struct bt_trace *trace_class,
- struct bt_clock_class *clock_class);
-
-/** @} */
-
-/**
-@name Stream class children functions
-@{
-*/
-
-/**
-@brief Returns the number of stream classes contained in the
- CTF IR trace class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the number
- of children stream classes.
-@returns Number of children stream classes
- contained in \p trace_class, or a negative
- value on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-*/
-extern int64_t bt_trace_get_stream_class_count(
- struct bt_trace *trace_class);
+extern uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace);
extern struct bt_stream_class *bt_trace_borrow_stream_class_by_index(
- struct bt_trace *trace_class, uint64_t index);
-
-/**
-@brief Returns the stream class at index \p index in the CTF IR trace
- class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the stream class.
-@param[in] index Index of the stream class to find.
-@returns Stream class at index \p index, or \c NULL
- on error.
-
-@prenotnull{trace_class}
-@pre \p index is lesser than the number of stream classes contained in
- the trace class \p trace_class (see
- bt_trace_get_stream_class_count()).
-@postrefcountsame{trace_class}
-
-@sa bt_trace_get_stream_class_by_id(): Finds a stream class by ID.
-@sa bt_trace_add_stream_class(): Adds a stream class to a trace class.
-*/
-static inline
-struct bt_stream_class *bt_trace_get_stream_class_by_index(
- struct bt_trace *trace_class, uint64_t index)
-{
- return bt_get(bt_trace_borrow_stream_class_by_index(
- trace_class, index));
-}
+ struct bt_trace *trace, uint64_t index);
extern struct bt_stream_class *bt_trace_borrow_stream_class_by_id(
- struct bt_trace *trace_class, uint64_t id);
-
-/**
-@brief Returns the stream class with ID \c id found in the CTF IR
- trace class \p trace_class.
+ struct bt_trace *trace, uint64_t id);
-@param[in] trace_class Trace class of which to get the stream class.
-@param[in] id ID of the stream class to find.
-@returns Stream class with ID \p id, or \c NULL
- on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-@postsuccessrefcountretinc
-
-@sa bt_trace_get_stream_class_by_index(): Returns the stream class contained
- in a given trace class at a given index.
-@sa bt_trace_add_stream_class(): Adds a stream class to a trace class.
-*/
-static inline
-struct bt_stream_class *bt_trace_get_stream_class_by_id(
- struct bt_trace *trace_class, uint64_t id)
-{
- return bt_get(bt_trace_borrow_stream_class_by_id(trace_class, id));
-}
-
-/**
-@brief Adds the CTF IR stream class \p stream_class to the
- CTF IR trace class \p trace_class.
-
-On success, \p stream_class becomes the child of \p trace_class.
-
-You can only add a given stream class to one trace class.
-
-You can call this function even if \p trace_class is frozen.
-
-This function tries to resolve the needed
-\link ctfirfieldtypes CTF IR field type\endlink of the dynamic field
-types that are found anywhere in the root field types of
-\p stream_class and of all its currently contained
-\link ctfireventclass CTF IR event classes\endlink. If any automatic
-resolving fails, then this function fails.
-
-@param[in] trace_class Trace class to which to add \p stream_class.
-@param[in] stream_class Stream class to add to \p trace_class.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{stream_class}
-@postrefcountsame{trace_class}
-@postsuccessrefcountinc{stream_class}
-@postsuccessfrozen{stream_class}
-
-@sa bt_trace_get_stream_class_by_index(): Returns the stream class contained
- in a given trace class at a given index.
-@sa bt_trace_get_stream_class_by_id(): Finds a stream class by ID.
-*/
-extern int bt_trace_add_stream_class(struct bt_trace *trace_class,
- struct bt_stream_class *stream_class);
-
-/** @} */
-
-/**
-@name Stream children functions
-@{
-*/
-
-/**
-@brief Returns the number of streams contained in the CTF IR trace
- class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the number
- of children streams.
-@returns Number of children streams
- contained in \p trace_class, or a negative
- value on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-*/
-extern int64_t bt_trace_get_stream_count(struct bt_trace *trace_class);
+extern uint64_t bt_trace_get_stream_count(struct bt_trace *trace);
extern struct bt_stream *bt_trace_borrow_stream_by_index(
- struct bt_trace *trace_class, uint64_t index);
-
-/**
-@brief Returns the stream at index \p index in the CTF IR trace
- class \p trace_class.
-
-@param[in] trace_class Trace class of which to get the stream.
-@param[in] index Index of the stream to find.
-@returns Stream at index \p index, or \c NULL
- on error.
-
-@prenotnull{trace_class}
-@pre \p index is lesser than the number of streams contained in
- the trace class \p trace_class (see
- bt_trace_get_stream_count()).
-@postrefcountsame{trace_class}
-*/
-static inline
-struct bt_stream *bt_trace_get_stream_by_index(
- struct bt_trace *trace_class, uint64_t index)
-{
- return bt_get(bt_trace_borrow_stream_by_index(trace_class, index));
-}
-
-/** @} */
-
-/**
-@name Misc. functions
-@{
-*/
-
-/**
-@brief Returns whether or not the CTF IR trace class \p trace_class
- is static.
-
-It is guaranteed that a static trace class will never contain new
-streams, stream classes, or clock classes. A static class is always
-frozen.
-
-This function returns #BT_TRUE if bt_trace_set_is_static() was
-previously called on it.
+ struct bt_trace *trace, uint64_t index);
-@param[in] trace_class Trace class to check.
-@returns #BT_TRUE if \p trace_class is static,
+extern struct bt_stream *bt_trace_borrow_stream_by_id(
+ struct bt_trace *trace, uint64_t id);
-@sa bt_trace_set_is_static(): Makes a trace class static.
-*/
-extern bt_bool bt_trace_is_static(struct bt_trace *trace_class);
+extern bt_bool bt_trace_is_static(struct bt_trace *trace);
-/**
-@brief Makes the CTF IR trace class \p trace_class static.
+extern int bt_trace_make_static(struct bt_trace *trace);
-A static trace class is frozen and you cannot call any modifying
-function on it:
-
-- bt_trace_add_stream_class()
-- bt_trace_add_clock_class()
-- bt_trace_set_environment_field()
-- bt_trace_set_environment_field_integer()
-- bt_trace_set_environment_field_string()
-- bt_trace_add_is_static_listener()
-
-You cannot create a stream with bt_stream_create() with any of the
-stream classes of a static trace class.
-
-@param[in] trace_class Trace class to make static.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@postrefcountsame{trace_class}
-@postsuccessfrozen{trace_class}
-
-@sa bt_trace_is_static(): Checks whether or not a given trace class
- is static.
-@sa bt_trace_add_is_static_listener(): Adds a listener to a trace
- class which is called when the trace class is made static.
-*/
-extern int bt_trace_set_is_static(struct bt_trace *trace_class);
-
-/**
-@brief Adds the listener \p listener to the CTF IR trace class
- \p trace_class which is called when the trace is made static.
-
-\p listener is called with \p data, the user data, the first time
-bt_trace_set_is_static() is called on \p trace_class.
-
-When the trace is destroyed, or when you remove the added listener with
-bt_trace_remove_is_static_listener(), \p listener_removed is called
-if it's not \c NULL. You can use \p listener_removed to free any dynamic
-data which exists only for the added listener. You cannot call
-any function which modifies \p trace_class during the execution of
-\p listener_removed, including bt_trace_remove_is_static_listener().
-
-This function fails if \p trace_class is already static: you need to
-check the condition first with bt_trace_is_static().
-
-On success, this function returns a unique numeric identifier for this
-listener within \p trace. You can use this identifier to remove the
-specific listener you added with
-bt_trace_remove_is_static_listener().
-
-@param[in] trace_class Trace class to which to add the
- listener.
-@param[in] listener Listener to add to \p trace_class.
-@param[in] listener_removed Remove listener called when \p listener
- is removed from \p trace_class, or
- \c NULL if you don't need a remove
- listener.
-@param[in] data User data passed when \p listener or
- \p listener_removed is called.
-@returns A unique numeric identifier for this
- listener on success (0 or greater), or a
- negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{listener}
-@pre \p trace_class is not static.
-@postrefcountsame{trace_class}
-
-@sa bt_trace_remove_is_static_listener(): Removes a "trace is
- static" listener from a trace class previously added with this
- function.
-@sa bt_trace_is_static(): Checks whether or not a given trace class
- is static.
-@sa bt_trace_set_is_static(): Makes a trace class static.
-*/
extern int bt_trace_add_is_static_listener(
- struct bt_trace *trace_class,
+ struct bt_trace *trace,
bt_trace_is_static_listener listener,
- bt_trace_listener_removed listener_removed, void *data);
-
-/**
-@brief Removes the "trace is static" listener identified by
- \p listener_id from the trace class \p trace_class.
-
-@param[in] trace_class Trace class from which to remove the listener
- identified by \p listener_id.
-@param[in] listener_id Identifier of the listener to remove from
- \p trace_class.
-@returns 0 if this function removed the listener, or
- a negative value on error.
+ bt_trace_listener_removed listener_removed, void *data,
+ uint64_t *listener_id);
-@prenotnull{trace_class}
-@pre \p listener_id is the identifier of a listener that you previously
- added with bt_trace_add_is_static_listener() and did not
- already remove with this function.
-@postrefcountsame{trace_class}
-
-@sa bt_trace_add_is_static_listener(): Adds a listener to a trace
- class which is called when the trace class is made static.
-*/
extern int bt_trace_remove_is_static_listener(
- struct bt_trace *trace_class, int listener_id);
-
-/**
-@brief Accepts the visitor \p visitor to visit the hierarchy of the
- CTF IR trace class \p trace_class.
-
-This function traverses the hierarchy of \p trace_class in pre-order
-and calls \p visitor on each element.
-
-The trace class itself is visited first, then, for each children stream
-class, the stream class itself, and all its children event classes.
-
-@param[in] trace_class Trace class to visit.
-@param[in] visitor Visiting function.
-@param[in] data User data.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{trace_class}
-@prenotnull{visitor}
-*/
-extern int bt_trace_visit(struct bt_trace *trace_class,
- bt_visitor visitor, void *data);
-
-/** @} */
-
-/** @} */
+ struct bt_trace *trace, uint64_t listener_id);
#ifdef __cplusplus
}
#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <stdint.h>
struct search_query {
int found;
};
-BT_HIDDEN
-const char *get_byte_order_string(enum bt_byte_order byte_order);
+static inline
+uint64_t bt_util_ns_from_value(uint64_t frequency, uint64_t value_cycles)
+{
+ uint64_t ns;
+
+ if (frequency == UINT64_C(1000000000)) {
+ ns = value_cycles;
+ } else {
+ double dblres = ((1e9 * (double) value_cycles) / (double) frequency);
+
+ if (dblres >= (double) UINT64_MAX) {
+ /* Overflows uint64_t */
+ ns = UINT64_C(-1);
+ } else {
+ ns = (uint64_t) dblres;
+ }
+ }
+
+ return ns;
+}
+
+static inline
+int bt_util_ns_from_origin(struct bt_clock_class *clock_class, uint64_t value,
+ int64_t *ns_from_origin)
+{
+ int ret = 0;
+ uint64_t value_ns_unsigned;
+ int64_t value_ns_signed;
+
+ if (clock_class->base_offset.overflows) {
+ ret = -1;
+ goto end;
+ }
+
+ /* Initialize to clock class's base offset */
+ *ns_from_origin = clock_class->base_offset.value_ns;
+
+ /* Add given value in cycles */
+ value_ns_unsigned = bt_util_ns_from_value(clock_class->frequency, value);
+ if (value_ns_unsigned >= (uint64_t) INT64_MAX) {
+ /*
+ * FIXME: `value_ns_unsigned` could be greater than
+ * `INT64_MAX` in fact: in this case, we need to
+ * subtract `INT64_MAX` from `value_ns_unsigned`, make
+ * sure that the difference is less than `INT64_MAX`,
+ * and try to add them one after the other to
+ * `*ns_from_origin`.
+ */
+ ret = -1;
+ goto end;
+ }
+
+ value_ns_signed = (int64_t) value_ns_unsigned;
+ BT_ASSERT(value_ns_signed >= 0);
+
+ if (*ns_from_origin <= 0) {
+ goto add_value;
+ }
+
+ if (value_ns_signed > INT64_MAX - *ns_from_origin) {
+ ret = -1;
+ goto end;
+ }
+
+add_value:
+ *ns_from_origin += value_ns_signed;
+
+end:
+ return ret;
+}
+
+static inline
+bool bt_util_value_is_in_range_signed(uint64_t size, int64_t value)
+{
+ int64_t min_value = UINT64_C(-1) << (size - 1);
+ int64_t max_value = (UINT64_C(1) << (size - 1)) - 1;
+ return value >= min_value && value <= max_value;
+}
+
+static inline
+bool bt_util_value_is_in_range_unsigned(unsigned int size, uint64_t value)
+{
+ uint64_t max_value = (size == 64) ? UINT64_MAX :
+ (UINT64_C(1) << size) - 1;
+ return value <= max_value;
+}
#endif /* BABELTRACE_CTF_IR_UTILS_INTERNAL_H */
+++ /dev/null
-#ifndef BABELTRACE_CTF_IR_UTILS_H
-#define BABELTRACE_CTF_IR_UTILS_H
-
-/*
- * BabelTrace - CTF IR: Utilities
- *
- * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The Common Trace Format (CTF) Specification is available at
- * http://www.efficios.com/ctf
- */
-
-/* For bt_bool */
-#include <babeltrace/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
-@defgroup ctfirutils CTF IR utilities
-@ingroup ctfir
-@brief CTF IR utilities.
-
-@code
-#include <babeltrace/ctf-ir/utils.h>
-@endcode
-
-@file
-@brief CTF IR utilities functions.
-@sa ctfirutils
-
-@addtogroup ctfirutils
-@{
-*/
-
-/**
-@brief Returns whether or not the string \p identifier is a valid
- identifier according to CTF.
-
-This function returns a negative value if \p identifier is a CTF keyword
-or if it does not meet any other imposed requirement.
-
-@param[in] identifier String to test.
-@returns #BT_TRUE if \p identifier is a valid CTF
- identifier, or #BT_FALSE otherwise.
-
-@prenotnull{identifier}
-*/
-extern bt_bool bt_identifier_is_valid(const char *identifier);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BABELTRACE_CTF_IR_UTILS_H */
+++ /dev/null
-#ifndef BABELTRACE_CTF_IR_VALIDATION_INTERNAL_H
-#define BABELTRACE_CTF_IR_VALIDATION_INTERNAL_H
-
-/*
- * Babeltrace - CTF IR: Validation of trace, stream class, and event class
- *
- * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/values.h>
-#include <babeltrace/babeltrace-internal.h>
-
-struct bt_trace;
-struct bt_stream_class;
-struct bt_event_class;
-struct bt_field_type;
-
-typedef struct bt_field_type *(*bt_validation_flag_copy_field_type_func)(
- struct bt_field_type *);
-
-enum bt_validation_flag {
- BT_VALIDATION_FLAG_TRACE = 1,
- BT_VALIDATION_FLAG_STREAM = 2,
- BT_VALIDATION_FLAG_EVENT = 4,
-};
-
-/*
- * Validation output structure.
- *
- * This is where the results of the validation function go. The field
- * types are the validated ones which should replace the original field
- * types of a trace, a stream class, and an event class.
- *
- * `valid_flags` contains the results of the validation.
- */
-struct bt_validation_output {
- struct bt_field_type *packet_header_type;
- struct bt_field_type *packet_context_type;
- struct bt_field_type *event_header_type;
- struct bt_field_type *stream_event_ctx_type;
- struct bt_field_type *event_context_type;
- struct bt_field_type *event_payload_type;
- enum bt_validation_flag valid_flags;
-};
-
-/*
- * This function resolves and validates the field types of an event
- * class, a stream class, and a trace. Copies are created if needed
- * and the resulting field types to use are placed in the `output`
- * validation structure, which also contains the results of the
- * validation. Copies can replace the original field types of a trace,
- * a stream class, and an event class using
- * bt_validation_replace_types().
- *
- * The current known validity of the field types of the trace,
- * stream class, and event class must be indicated with the
- * `trace_valid`, `stream_class_valid`, and `event_class_valid`
- * parameters. If a class is valid, its field types are not copied,
- * validated, or resolved during this call.
- *
- * The validation flags `validate_flags` indicate which classes should
- * have their field types validated.
- *
- * All parameters are owned by the caller.
- */
-BT_HIDDEN
-int bt_validate_class_types(struct bt_value *environment,
- struct bt_field_type *packet_header_type,
- struct bt_field_type *packet_context_type,
- struct bt_field_type *event_header_type,
- struct bt_field_type *stream_event_ctx_type,
- struct bt_field_type *event_context_type,
- struct bt_field_type *event_payload_type,
- int trace_valid, int stream_class_valid, int event_class_valid,
- struct bt_validation_output *output,
- enum bt_validation_flag validate_flags,
- bt_validation_flag_copy_field_type_func copy_field_type_func);
-
-/*
- * This function replaces the actual field types of a trace, a stream
- * class, and an event class with the appropriate field types contained
- * in a validation output structure.
- *
- * The replace flags `replace_flags` indicate which classes should have
- * their field types replaced.
- *
- * Note that the field types that are not used in the validation output
- * structure are still owned by it at the end of this call.
- * bt_validation_output_put_types() should be called to clean the
- * structure.
- *
- * All parameters are owned by the caller.
- */
-BT_HIDDEN
-void bt_validation_replace_types(struct bt_trace *trace,
- struct bt_stream_class *stream_class,
- struct bt_event_class *event_class,
- struct bt_validation_output *output,
- enum bt_validation_flag replace_flags);
-
-/*
- * This function puts all the field types contained in a given
- * validation output structure.
- *
- * `output` is owned by the caller and is not freed here.
- */
-BT_HIDDEN
-void bt_validation_output_put_types(
- struct bt_validation_output *output);
-
-#endif /* BABELTRACE_CTF_IR_VALIDATION_INTERNAL_H */
+++ /dev/null
-#ifndef BABELTRACE_CTF_IR_VISITOR_INTERNAL_H
-#define BABELTRACE_CTF_IR_VISITOR_INTERNAL_H
-
-/*
- * BabelTrace - CTF IR: Visitor internal
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/ctf-ir/visitor.h>
-#include <babeltrace/babeltrace-internal.h>
-
-typedef void *(*bt_child_accessor)(void *object, int index);
-typedef int64_t (*bt_child_count_accessor)(void *object);
-typedef int (*bt_child_visitor)(void *object, bt_visitor visitor,
- void *data);
-
-struct bt_visitor_object {
- enum bt_visitor_object_type type;
- void *object;
-};
-
-BT_HIDDEN
-int visitor_helper(struct bt_visitor_object *root,
- bt_child_count_accessor child_counter,
- bt_child_accessor child_accessor,
- bt_child_visitor child_visitor,
- bt_visitor visitor,
- void *data);
-
-#endif /* BABELTRACE_CTF_IR_VISITOR_INTERNAL_H */
+++ /dev/null
-#ifndef BABELTRACE_CTF_IR_VISITOR_H
-#define BABELTRACE_CTF_IR_VISITOR_H
-
-/*
- * BabelTrace - CTF IR: Visitor
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The Common Trace Format (CTF) Specification is available at
- * http://www.efficios.com/ctf
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
-@defgroup ctfirvisitor CTF IR visitor
-@ingroup ctfir
-@brief CTF IR visitor.
-
-@code
-#include <babeltrace/ctf-ir/visitor.h>
-@endcode
-
-A CTF IR <strong><em>visitor</em></strong> is a function that you
-can use to visit the hierarchy of a
-\link ctfirtraceclass CTF IR trace class\endlink with
-bt_trace_visit() or of a
-\link ctfirstreamclass CTF IR stream class\endlink with
-bt_stream_class_visit().
-
-The traversal of the object's hierarchy is always done in a
-pre-order fashion.
-
-@sa ctfirstreamclass
-@sa ctfirtraceclass
-
-@file
-@brief CTF IR visitor types and functions.
-@sa ctfirvisitor
-
-@addtogroup ctfirvisitor
-@{
-*/
-
-/**
-@struct bt_object
-@brief A CTF IR object wrapper.
-
-This structure wraps both a CTF IR object and its type
-(see #bt_object_type). It is used in the visiting function.
-
-You can use the bt_object_get_type() and
-bt_object_get_object() accessors to get the type and wrapped
-CTF IR object of a CTF IR object wrapper.
-
-A CTF IR object wrapper has <strong>no reference count</strong>: do \em
-not use bt_put() or bt_get() on it.
-
-@sa ctfirvisitor
-*/
-struct bt_visitor_object;
-
-/**
-@brief CTF IR object wrapper type.
-*/
-enum bt_visitor_object_type {
- /// Unknown (used for errors).
- BT_VISITOR_OBJECT_TYPE_UNKNOWN = -1,
-
- /// \ref ctfirtraceclass.
- BT_VISITOR_OBJECT_TYPE_TRACE = 0,
-
- /// \ref ctfirstreamclass.
- BT_VISITOR_OBJECT_TYPE_STREAM_CLASS = 1,
-
- /// \ref ctfirstream.
- BT_VISITOR_OBJECT_TYPE_STREAM = 2,
-
- /// \ref ctfireventclass.
- BT_VISITOR_OBJECT_TYPE_EVENT_CLASS = 3,
-
- /// \ref ctfirevent.
- BT_VISITOR_OBJECT_TYPE_EVENT = 4,
-
- /// Number of entries in this enumeration.
- BT_VISITOR_OBJECT_TYPE_NR,
-};
-
-/**
-@brief Visting function type.
-
-A function of this type is called by bt_trace_visit() or
-bt_stream_class_visit() when visiting the CTF IR object wrapper
-\p object.
-
-\p object has <strong>no reference count</strong>: do \em not use
-bt_put() or bt_get() on it.
-
-@param[in] object Currently visited CTF IR object wrapper.
-@param[in] data User data.
-@returns 0 on success, or a negative value on error.
-
-@prenotnull{object}
-
-@sa bt_trace_visit(): Accepts a visitor to visit a trace class.
-@sa bt_stream_class_visit(): Accepts a visitor to visit a stream
- class.
-*/
-typedef int (*bt_visitor)(struct bt_visitor_object *object,
- void *data);
-
-/**
-@brief Returns the type of the CTF IR object wrapped by the CTF IR
- object wrapper \p object.
-
-@param[in] object Object wrapper of which to get the type.
-@returns Type of \p object.
-
-@prenotnull{object}
-
-@sa bt_visitor_object_get_object(): Returns the object wrapped by a given
- CTF IR object wrapper.
-*/
-enum bt_visitor_object_type bt_visitor_object_get_type(
- struct bt_visitor_object *object);
-
-/**
-@brief Returns the CTF IR object wrapped by the CTF IR object
- wrapper \p object.
-
-The reference count of \p object is \em not incremented by this
-function. On success, you must call bt_get() on the return value to
-have your own reference.
-
-@param[in] object Object wrapper of which to get the wrapped
- CTF IR object.
-@returns CTF IR object wrapped by \p object.
-
-@prenotnull{object}
-@post The reference count of the returned object is not modified.
-
-@sa bt_visitor_object_get_type(): Returns the type of a given
- CTF IR object wrapper.
-*/
-void *bt_visitor_object_get_object(struct bt_visitor_object *object);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BABELTRACE_CTF_IR_VISITOR_H */
#include <sys/stat.h>
#include <fcntl.h>
#include <babeltrace/align-internal.h>
+#include <babeltrace/endian-internal.h>
#include <babeltrace/common-internal.h>
#include <babeltrace/mmap-align-internal.h>
#include <babeltrace/types.h>
#define PACKET_LEN_INCREMENT (bt_common_get_page_size() * 8 * CHAR_BIT)
+#if (BYTE_ORDER == BIG_ENDIAN)
+# define BT_CTF_MY_BYTE_ORDER BT_CTF_BYTE_ORDER_BIG_ENDIAN
+#else
+# define BT_CTF_MY_BYTE_ORDER BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
+#endif
+
struct bt_ctf_stream_pos {
int fd;
int prot; /* mmap protection */
};
BT_HIDDEN
-int visitor_helper(struct bt_ctf_visitor_object *root,
+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,
#endif /* __FLOAT_WORD_ORDER */
#endif /* FLOAT_WORD_ORDER */
-#if (BYTE_ORDER == BIG_ENDIAN)
-# define BT_MY_BYTE_ORDER BT_BYTE_ORDER_BIG_ENDIAN
-#else
-# define BT_MY_BYTE_ORDER BT_BYTE_ORDER_LITTLE_ENDIAN
-#endif
-
#endif /* _BABELTRACE_ENDIAN_H */
*/
#include <glib.h>
-#include <babeltrace/ctf-ir/clock-value-set-internal.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/graph/notification.h>
struct bt_notification_inactivity {
struct bt_notification parent;
- struct bt_clock_value_set cv_set;
+ struct bt_clock_value *default_cv;
};
#endif /* BABELTRACE_GRAPH_NOTIFICATION_INACTIVITY_INTERNAL_H */
extern
struct bt_notification *bt_notification_inactivity_create(
- struct bt_private_connection_private_notification_iterator *notification_iterator);
+ struct bt_private_connection_private_notification_iterator *notification_iterator,
+ struct bt_clock_class *default_clock_class);
-extern int bt_notification_inactivity_set_clock_value(
- struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default);
+extern int bt_notification_inactivity_set_default_clock_value(
+ struct bt_notification *notif, uint64_t raw_value);
extern struct bt_clock_value *bt_notification_inactivity_borrow_default_clock_value(
struct bt_notification *notif);
#include <babeltrace/compiler-internal.h>
#include <babeltrace/ctf-ir/packet.h>
#include <babeltrace/graph/notification-internal.h>
-#include <babeltrace/ctf-ir/clock-value-set-internal.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/assert-internal.h>
struct bt_notification_stream_begin {
struct bt_notification parent;
struct bt_stream *stream;
- struct bt_clock_value_set cv_set;
+ struct bt_clock_value *default_cv;
};
struct bt_notification_stream_end {
struct bt_notification parent;
struct bt_stream *stream;
- struct bt_clock_value_set cv_set;
+ struct bt_clock_value *default_cv;
};
#endif /* BABELTRACE_GRAPH_NOTIFICATION_STREAM_INTERNAL_H */
return bt_get(bt_notification_stream_begin_borrow_stream(notification));
}
-extern int bt_notification_stream_begin_set_clock_value(
- struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default);
+extern int bt_notification_stream_begin_set_default_clock_value(
+ struct bt_notification *notif, uint64_t value_cycles);
extern struct bt_clock_value *bt_notification_stream_begin_borrow_default_clock_value(
struct bt_notification *notif);
return bt_get(bt_notification_stream_end_borrow_stream(notification));
}
-extern int bt_notification_stream_end_set_clock_value(
- struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default);
+extern int bt_notification_stream_end_set_default_clock_value(
+ struct bt_notification *notif, uint64_t value_cycles);
extern struct bt_clock_value *bt_notification_stream_end_borrow_default_clock_value(
struct bt_notification *notif);
#include <babeltrace/babeltrace-internal.h>
#include <stdarg.h>
+#ifndef BT_LOG_TAG
+# error Please define a tag with BT_LOG_TAG before including this file.
+#endif
+
#define BT_LOG_OUTPUT_LEVEL bt_lib_log_level
#include <babeltrace/logging-internal.h>
* `PRIi64`.
*
* The Babeltrace extension conversion specifier is accepted. Its syntax
- * is:
+ * is either `%!u` to format a UUID (`bt_uuid` type) or:
*
* 1. Introductory `%!` sequence.
*
*
* The available format specifiers are:
*
- * `r`:
- * Reference count information. The parameter is any Babeltrace
- * object.
- *
* `F`:
* CTF IR field type. The parameter type is `struct bt_field_type *`.
*
* `g`:
* Graph. The parameter type is `struct bt_graph *`.
*
- * `u`:
+ * `l`:
* Plugin. The parameter type is `struct bt_plugin *`.
*
* `o`:
* Object pool. The parameter type is `struct bt_object_pool *`.
*
+ * `O`:
+ * Object. The parameter type is `struct bt_object *`.
+ *
* Conversion specifier examples:
*
* %!f
* the last one. Therefore you must put this separator in the format
* string between two Babeltrace objects, e.g.:
*
- * BT_LIB_LOGW("Message: count=%u, %!E, %!+C", count, event_class,
+ * BT_LIB_LOGW("Message: count=%u, %!E, %!+K", count, event_class,
* clock_class);
*
* Example with a custom prefix:
--- /dev/null
+#ifndef BABELTRACE_PROPERTY_INTERNAL_H
+#define BABELTRACE_PROPERTY_INTERNAL_H
+
+/*
+ * 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.
+ */
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/property.h>
+#include <babeltrace/types.h>
+#include <glib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct bt_property {
+ enum bt_property_availability avail;
+};
+
+struct bt_property_uint {
+ struct bt_property base;
+ uint64_t value;
+};
+
+static inline
+void bt_property_uint_set(struct bt_property_uint *prop, uint64_t value)
+{
+ BT_ASSERT(prop);
+ prop->base.avail = BT_PROPERTY_AVAILABILITY_AVAILABLE;
+ prop->value = value;
+}
+
+static inline
+void bt_property_uint_init(struct bt_property_uint *prop,
+ enum bt_property_availability avail, uint64_t value)
+{
+ BT_ASSERT(prop);
+ prop->base.avail = avail;
+ prop->value = value;
+}
+
+#endif /* BABELTRACE_PROPERTY_INTERNAL_H */
--- /dev/null
+#ifndef BABELTRACE_PROPERTY_H
+#define BABELTRACE_PROPERTY_H
+
+/*
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum bt_property_availability {
+ BT_PROPERTY_AVAILABILITY_AVAILABLE,
+ BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_PROPERTY_H */
* SOFTWARE.
*/
+#include <stdint.h>
+
#ifdef __cplusplus
extern "C" {
#endif
*/
typedef int bt_bool;
+typedef const uint8_t *bt_uuid;
+
/** @} */
#ifdef __cplusplus
libctf_ir_la_SOURCES = \
attributes.c \
clock-class.c \
+ clock-value.c \
event.c \
event-class.c \
event-header-field.c \
packet.c \
packet-context-field.c \
packet-header-field.c \
+ resolve-field-path.c \
stream.c \
stream-class.c \
trace.c \
- utils.c \
- resolve.c \
- validation.c \
- visitor.c
+ utils.c
libctf_ir_la_LIBADD = $(UUID_LIBS)
#include <babeltrace/compat/uuid-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/ctf-ir/clock-value-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/assert-internal.h>
-static
-void bt_clock_class_destroy(struct bt_object *obj);
-
-static
-struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class);
+#define BT_ASSERT_PRE_CLOCK_CLASS_HOT(_cc) \
+ BT_ASSERT_PRE_HOT((_cc), "Clock class", ": %!+K", (_cc))
static
-void bt_clock_value_destroy(struct bt_clock_value *clock_value);
-
-BT_HIDDEN
-bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class)
+void destroy_clock_class(struct bt_object *obj)
{
- return clock_class && clock_class->name;
-}
+ struct bt_clock_class *clock_class = (void *) obj;
-int bt_clock_class_set_name(struct bt_clock_class *clock_class,
- const char *name)
-{
- int ret = 0;
+ BT_LIB_LOGD("Destroying clock class: %!+K", clock_class);
- if (!clock_class) {
- BT_LOGW_STR("Invalid parameter: clock class is NULL.");
- ret = -1;
- goto end;
+ if (clock_class->name.str) {
+ g_string_free(clock_class->name.str, TRUE);
}
- if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
- clock_class, bt_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
-
- if (!bt_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->description.str) {
+ g_string_free(clock_class->description.str, TRUE);
}
- 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;
+ bt_object_pool_finalize(&clock_class->cv_pool);
+ g_free(clock_class);
}
static
-bool validate_freq(struct bt_clock_class *clock_class,
- const char *name, uint64_t freq)
+void free_clock_value(struct bt_clock_value *clock_value,
+ struct bt_clock_class *clock_class)
{
- 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_clock_value_destroy(clock_value);
}
-static
-void bt_clock_class_free_clock_value(struct bt_clock_value *clock_value,
- struct bt_clock_class *clock_class)
+static inline
+void set_base_offset(struct bt_clock_class *clock_class)
{
- bt_clock_value_destroy(clock_value);
+ uint64_t offset_cycles_ns;
+
+ /* Initialize nanosecond timestamp to clock's offset in seconds */
+ if (clock_class->offset_seconds <= (INT64_MIN / INT64_C(1000000000) - 1) ||
+ clock_class->offset_seconds >= (INT64_MAX / INT64_C(1000000000)) - 1) {
+ /*
+ * Overflow: offset in seconds converted to nanoseconds
+ * is outside the int64_t range. We also subtract 1 here
+ * to leave "space" for the offset in cycles converted
+ * to nanoseconds (which is always less than 1 second by
+ * contract).
+ */
+ clock_class->base_offset.overflows = true;
+ goto end;
+ }
+
+ /* Offset (seconds) to nanoseconds */
+ clock_class->base_offset.value_ns = clock_class->offset_seconds *
+ INT64_C(1000000000);
+
+ /* Add offset in cycles */
+ BT_ASSERT(clock_class->offset_cycles < clock_class->frequency);
+ offset_cycles_ns = bt_util_ns_from_value(clock_class->frequency,
+ clock_class->offset_cycles);
+ BT_ASSERT(offset_cycles_ns < 1000000000);
+ clock_class->base_offset.value_ns += (int64_t) offset_cycles_ns;
+ clock_class->base_offset.overflows = false;
+
+end:
+ return;
}
-struct bt_clock_class *bt_clock_class_create(const char *name,
- uint64_t freq)
+struct bt_clock_class *bt_clock_class_create(void)
{
int ret;
struct bt_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;
- }
+ BT_LOGD_STR("Creating default clock class object");
clock_class = g_new0(struct bt_clock_class, 1);
if (!clock_class) {
goto error;
}
- clock_class->precision = 1;
- clock_class->frequency = freq;
- bt_object_init_shared(&clock_class->base, bt_clock_class_destroy);
+ bt_object_init_shared(&clock_class->base, destroy_clock_class);
+ clock_class->name.str = g_string_new(NULL);
+ if (!clock_class->name.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ goto error;
+ }
- if (name) {
- ret = bt_clock_class_set_name(clock_class, name);
- if (ret) {
- /* bt_clock_class_set_name() logs errors */
- goto error;
- }
+ clock_class->description.str = g_string_new(NULL);
+ if (!clock_class->description.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ goto error;
}
+ clock_class->frequency = UINT64_C(1000000000);
+ clock_class->is_absolute = BT_TRUE;
+ set_base_offset(clock_class);
ret = bt_object_pool_initialize(&clock_class->cv_pool,
(bt_object_pool_new_object_func) bt_clock_value_new,
(bt_object_pool_destroy_object_func)
- bt_clock_class_free_clock_value,
+ free_clock_value,
clock_class);
if (ret) {
BT_LOGE("Failed to initialize clock value pool: ret=%d",
goto error;
}
- BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
- clock_class, name);
- return clock_class;
+ BT_LIB_LOGD("Created clock class object: %!+K", clock_class);
+ goto end;
+
error:
BT_PUT(clock_class);
- return clock_class;
-}
-
-const char *bt_clock_class_get_name(struct bt_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;
+ return clock_class;
}
-const char *bt_clock_class_get_description(
+const char *bt_clock_class_get_name(
struct bt_clock_class *clock_class)
{
- const char *ret = NULL;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return clock_class->name.value;
+}
- if (!clock_class) {
- BT_LOGW_STR("Invalid parameter: clock class is NULL.");
- goto end;
- }
+int bt_clock_class_set_name(struct bt_clock_class *clock_class,
+ const char *name)
+{
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ g_string_assign(clock_class->name.str, name);
+ clock_class->name.value = clock_class->name.str->str;
+ BT_LIB_LOGV("Set clock class's name: %!+K", clock_class);
+ return 0;
+}
- if (clock_class->description) {
- ret = clock_class->description->str;
- }
-end:
- return ret;
+const char *bt_clock_class_get_description(struct bt_clock_class *clock_class)
+{
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return clock_class->description.value;
}
int bt_clock_class_set_description(struct bt_clock_class *clock_class,
- const char *desc)
+ const char *descr)
{
- 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_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_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_clock_class_get_name(clock_class), desc);
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(descr, "Description");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ g_string_assign(clock_class->description.str, descr);
+ clock_class->description.value = clock_class->description.str->str;
+ BT_LIB_LOGV("Set clock class's description: %!+K",
+ clock_class);
+ return 0;
}
-uint64_t bt_clock_class_get_frequency(
- struct bt_clock_class *clock_class)
+uint64_t bt_clock_class_get_frequency(struct bt_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_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return clock_class->frequency;
}
int bt_clock_class_set_frequency(struct bt_clock_class *clock_class,
- uint64_t freq)
+ uint64_t frequency)
{
- 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_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
-
- if (!validate_freq(clock_class, bt_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_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_clock_class_get_name(clock_class), freq);
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ BT_ASSERT_PRE(frequency != UINT64_C(-1) && frequency != 0,
+ "Invalid frequency: %![cc-]+K, new-freq=%" PRIu64,
+ clock_class, frequency);
+ BT_ASSERT_PRE(clock_class->offset_cycles < frequency,
+ "Offset (cycles) is greater than clock class's frequency: "
+ "%![cc-]+K, new-freq=%" PRIu64, clock_class, frequency);
+ clock_class->frequency = frequency;
+ set_base_offset(clock_class);
+ BT_LIB_LOGV("Set clock class's frequency: %!+K", clock_class);
+ return 0;
}
uint64_t bt_clock_class_get_precision(struct bt_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_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return clock_class->precision;
}
int bt_clock_class_set_precision(struct bt_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_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_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
-
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ BT_ASSERT_PRE(precision != UINT64_C(-1),
+ "Invalid precision: %![cc-]+K, new-precision=%" PRIu64,
+ clock_class, precision);
clock_class->precision = precision;
- BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
- clock_class, bt_clock_class_get_name(clock_class),
- precision);
-end:
- return ret;
+ BT_LIB_LOGV("Set clock class's precision: %!+K", clock_class);
+ return 0;
}
-int bt_clock_class_get_offset_s(struct bt_clock_class *clock_class,
- int64_t *offset_s)
+void bt_clock_class_get_offset(struct bt_clock_class *clock_class,
+ int64_t *seconds, uint64_t *cycles)
{
- 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_clock_class_get_name(clock_class),
- offset_s);
- ret = -1;
- goto end;
- }
-
- *offset_s = clock_class->offset_s;
-end:
- return ret;
-}
-
-int bt_clock_class_set_offset_s(struct bt_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_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_clock_class_get_name(clock_class),
- offset_s);
-end:
- return ret;
-}
-
-int bt_clock_class_get_offset_cycles(struct bt_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_clock_class_get_name(clock_class),
- offset);
- ret = -1;
- goto end;
- }
-
- *offset = clock_class->offset;
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(seconds, "Seconds (output)");
+ BT_ASSERT_PRE_NON_NULL(cycles, "Cycles (output)");
+ *seconds = clock_class->offset_seconds;
+ *cycles = clock_class->offset_cycles;
}
-int bt_clock_class_set_offset_cycles(struct bt_clock_class *clock_class,
- int64_t offset)
+int bt_clock_class_set_offset(struct bt_clock_class *clock_class,
+ int64_t seconds, uint64_t cycles)
{
- 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_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_clock_class_get_name(clock_class), offset);
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ BT_ASSERT_PRE(cycles < clock_class->frequency,
+ "Offset (cycles) is greater than clock class's frequency: "
+ "%![cc-]+K, new-offset-cycles=%" PRIu64, clock_class, cycles);
+ clock_class->offset_seconds = seconds;
+ clock_class->offset_cycles = cycles;
+ set_base_offset(clock_class);
+ BT_LIB_LOGV("Set clock class's offset: %!+K", clock_class);
+ return 0;
}
bt_bool bt_clock_class_is_absolute(struct bt_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_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return (bool) clock_class->is_absolute;
}
int bt_clock_class_set_is_absolute(struct bt_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_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_clock_class_get_name(clock_class),
- is_absolute);
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ clock_class->is_absolute = (bool) is_absolute;
+ BT_LIB_LOGV("Set clock class's absolute property: %!+K",
+ clock_class);
+ return 0;
}
-const unsigned char *bt_clock_class_get_uuid(
- struct bt_clock_class *clock_class)
+bt_uuid bt_clock_class_get_uuid(struct bt_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_clock_class_get_name(clock_class));
- ret = NULL;
- goto end;
- }
-
- ret = clock_class->uuid;
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ return clock_class->uuid.value;
}
int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
- const unsigned char *uuid)
+ bt_uuid 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_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_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_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_clock_class_freeze(struct bt_clock_class *clock_class)
-{
- if (!clock_class || clock_class->frozen) {
- return;
- }
-
- BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
- clock_class, bt_clock_class_get_name(clock_class));
- clock_class->frozen = 1;
-}
-
-static
-void bt_clock_class_destroy(struct bt_object *obj)
-{
- struct bt_clock_class *clock_class;
-
- clock_class = container_of(obj, struct bt_clock_class, base);
- BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
- obj, bt_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);
- }
-
- bt_object_pool_finalize(&clock_class->cv_pool);
- g_free(clock_class);
-}
-
-static
-void bt_clock_value_destroy(struct bt_clock_value *clock_value)
-{
- BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
- "clock-class-name=\"%s\"", clock_value,
- clock_value->clock_class,
- bt_clock_class_get_name(clock_value->clock_class));
- bt_put(clock_value->clock_class);
- g_free(clock_value);
-}
-
-static
-struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class)
-{
- struct bt_clock_value *ret = NULL;
-
- BT_LOGD("Creating clock value object: clock-class-addr=%p, "
- "clock-class-name=\"%s\"", clock_class,
- bt_clock_class_get_name(clock_class));
-
- if (!clock_class) {
- BT_LOGW_STR("Invalid parameter: clock class is NULL.");
- goto end;
- }
-
- ret = g_new0(struct bt_clock_value, 1);
- if (!ret) {
- BT_LOGE_STR("Failed to allocate one clock value.");
- goto end;
- }
-
- bt_object_init_unique(&ret->base);
- ret->clock_class = bt_get(clock_class);
- bt_clock_class_freeze(clock_class);
- BT_LOGD("Created clock value object: clock-value-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\", "
- "ns-from-epoch=%" PRId64 ", ns-from-epoch-overflows=%d",
- ret, clock_class, bt_clock_class_get_name(clock_class),
- ret->ns_from_epoch, ret->ns_from_epoch_overflows);
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-struct bt_clock_value *bt_clock_value_create(struct bt_clock_class *clock_class)
-{
- struct bt_clock_value *clock_value = NULL;
-
- BT_ASSERT(clock_class);
- clock_value = bt_object_pool_create_object(&clock_class->cv_pool);
- if (!clock_value) {
- BT_LIB_LOGE("Cannot allocate one clock value from clock class's clock value pool: "
- "%![cc-]+K", clock_class);
- goto error;
- }
-
- if (!clock_value->clock_class) {
- clock_value->clock_class = bt_get(clock_class);
- }
-
- goto end;
-
-error:
- if (clock_value) {
- bt_clock_value_recycle(clock_value);
- clock_value = NULL;
- }
-
-end:
- return clock_value;
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(uuid, "UUID");
+ BT_ASSERT_PRE_CLOCK_CLASS_HOT(clock_class);
+ memcpy(clock_class->uuid.uuid, uuid, BABELTRACE_UUID_LEN);
+ clock_class->uuid.value = clock_class->uuid.uuid;
+ BT_LIB_LOGV("Set clock class's UUID: %!+K", clock_class);
+ return 0;
}
BT_HIDDEN
-void bt_clock_value_recycle(struct bt_clock_value *clock_value)
+void _bt_clock_class_freeze(struct bt_clock_class *clock_class)
{
- struct bt_clock_class *clock_class;
-
- BT_ASSERT(clock_value);
- BT_LIB_LOGD("Recycling clock value: %!+k", clock_value);
-
- /*
- * Those are the important ordered steps:
- *
- * 1. Reset the clock value object, but do NOT put its clock
- * class's reference. This clock class contains the pool to
- * which we're about to recycle this clock value object, so
- * we must guarantee its existence thanks to this existing
- * reference.
- *
- * 2. Move the clock class reference to our `clock_class`
- * variable so that we can set the clock value's clock class
- * member to NULL before recycling it. We CANNOT do this
- * after we put the clock class reference because this
- * bt_put() could destroy the clock class, also destroying
- * its clock value pool, thus also destroying our clock value
- * object (this would result in an invalid write access).
- *
- * 3. Recycle the clock value object.
- *
- * 4. Put our clock class reference.
- */
- bt_clock_value_reset(clock_value);
- bt_clock_value_set_is_frozen(clock_value, false);
- clock_class = clock_value->clock_class;
BT_ASSERT(clock_class);
- clock_value->clock_class = NULL;
- bt_object_pool_recycle_object(&clock_class->cv_pool, clock_value);
- bt_put(clock_class);
-}
-
-int bt_clock_value_get_value(struct bt_clock_value *clock_value,
- uint64_t *raw_value)
-{
- int ret = 0;
-
- if (!clock_value || !raw_value) {
- BT_LOGW("Invalid parameter: clock value or raw value is NULL: "
- "clock-value-addr=%p, raw-value-addr=%p",
- clock_value, raw_value);
- ret = -1;
- goto end;
- }
-
- *raw_value = clock_value->value;
-end:
- return ret;
-}
-
-int bt_clock_value_get_value_ns_from_epoch(struct bt_clock_value *value,
- int64_t *ret_value_ns)
-{
- int ret = 0;
-
- if (!value || !ret_value_ns) {
- BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
- "clock-value-addr=%p, ret-value-addr=%p",
- value, ret_value_ns);
- ret = -1;
- goto end;
- }
-
- if (value->ns_from_epoch_overflows) {
- BT_LOGW("Clock value converted to nanoseconds from Epoch overflows the signed 64-bit integer range: "
- "clock-value-addr=%p, "
- "clock-class-offset-s=%" PRId64 ", "
- "clock-class-offset-cycles=%" PRId64 ", "
- "value=%" PRIu64,
- value, value->clock_class->offset_s,
- value->clock_class->offset,
- value->value);
- ret = -1;
- goto end;
- }
-
- *ret_value_ns = value->ns_from_epoch;
-
-end:
- return ret;
-}
-
-struct bt_clock_class *bt_clock_value_borrow_class(
- struct bt_clock_value *clock_value)
-{
- struct bt_clock_class *clock_class = NULL;
-
- if (!clock_value) {
- BT_LOGW_STR("Invalid parameter: clock value is NULL.");
- goto end;
- }
-
- clock_class = clock_value->clock_class;
-end:
- return clock_class;
-}
-
-BT_HIDDEN
-int bt_clock_class_compare(struct bt_clock_class *clock_class_a,
- struct bt_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;
+ if (clock_class->frozen) {
+ return;
}
- /* Equal */
- ret = 0;
-
-end:
- return ret;
+ BT_LIB_LOGD("Freezing clock class: %!+K", clock_class);
+ clock_class->frozen = 1;
}
-int bt_clock_class_cycles_to_ns(struct bt_clock_class *clock_class,
+int bt_clock_class_cycles_to_ns_from_origin(struct bt_clock_class *clock_class,
uint64_t cycles, int64_t *ns)
{
int ret;
- bool overflows;
BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
- BT_ASSERT_PRE_NON_NULL(ns, "Nanoseconds");
-
- ret = ns_from_epoch(clock_class, cycles, ns, &overflows);
+ BT_ASSERT_PRE_NON_NULL(ns, "Nanoseconds (output)");
+ ret = bt_util_ns_from_origin(clock_class, cycles, ns);
if (ret) {
- if (overflows) {
- BT_LIB_LOGW("Cannot convert cycles to nanoseconds "
- "from Epoch for given clock class: "
- "value overflow: %![cc-]+K, cycles=%" PRIu64,
- clock_class, cycles);
- } else {
- BT_LIB_LOGW("Cannot convert cycles to nanoseconds "
- "from Epoch for given clock class: "
- "%![cc-]+K, cycles=%" PRIu64,
- clock_class, cycles);
- }
-
- goto end;
+ BT_LIB_LOGW("Cannot convert cycles to nanoseconds "
+ "from origin for given clock class: "
+ "value overflows the signed 64-bit integer range: "
+ "%![cc-]+K, cycles=%" PRIu64,
+ clock_class, cycles);
}
-end:
return ret;
}
--- /dev/null
+/*
+ * 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 "CLOCK-VALUE"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/ctf-ir/clock-class-internal.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
+#include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/types.h>
+#include <babeltrace/compat/string-internal.h>
+#include <inttypes.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/assert-internal.h>
+
+BT_HIDDEN
+void bt_clock_value_destroy(struct bt_clock_value *clock_value)
+{
+ BT_LIB_LOGD("Destroying clock value: %!+k", clock_value);
+ bt_put(clock_value->clock_class);
+ g_free(clock_value);
+}
+
+BT_HIDDEN
+struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class)
+{
+ struct bt_clock_value *ret = NULL;
+
+ BT_ASSERT(clock_class);
+ BT_LIB_LOGD("Creating clock value object: %![cc-]+K=",
+ clock_class);
+ ret = g_new0(struct bt_clock_value, 1);
+ if (!ret) {
+ BT_LOGE_STR("Failed to allocate one clock value.");
+ goto end;
+ }
+
+ bt_object_init_unique(&ret->base);
+ ret->clock_class = bt_get(clock_class);
+ bt_clock_class_freeze(clock_class);
+ BT_LIB_LOGD("Created clock value object: %!+k", ret);
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+struct bt_clock_value *bt_clock_value_create(struct bt_clock_class *clock_class)
+{
+ struct bt_clock_value *clock_value = NULL;
+
+ BT_ASSERT(clock_class);
+ clock_value = bt_object_pool_create_object(&clock_class->cv_pool);
+ if (!clock_value) {
+ BT_LIB_LOGE("Cannot allocate one clock value from clock class's clock value pool: "
+ "%![cc-]+K", clock_class);
+ goto error;
+ }
+
+ if (likely(!clock_value->clock_class)) {
+ clock_value->clock_class = bt_get(clock_class);
+ }
+
+ goto end;
+
+error:
+ if (clock_value) {
+ bt_clock_value_recycle(clock_value);
+ clock_value = NULL;
+ }
+
+end:
+ return clock_value;
+}
+
+BT_HIDDEN
+void bt_clock_value_recycle(struct bt_clock_value *clock_value)
+{
+ struct bt_clock_class *clock_class;
+
+ BT_ASSERT(clock_value);
+ BT_LIB_LOGD("Recycling clock value: %!+k", clock_value);
+
+ /*
+ * Those are the important ordered steps:
+ *
+ * 1. Reset the clock value object, but do NOT put its clock
+ * class's reference. This clock class contains the pool to
+ * which we're about to recycle this clock value object, so
+ * we must guarantee its existence thanks to this existing
+ * reference.
+ *
+ * 2. Move the clock class reference to our `clock_class`
+ * variable so that we can set the clock value's clock class
+ * member to NULL before recycling it. We CANNOT do this
+ * after we put the clock class reference because this
+ * bt_put() could destroy the clock class, also destroying
+ * its clock value pool, thus also destroying our clock value
+ * object (this would result in an invalid write access).
+ *
+ * 3. Recycle the clock value object.
+ *
+ * 4. Put our clock class reference.
+ */
+ bt_clock_value_reset(clock_value);
+ clock_class = clock_value->clock_class;
+ BT_ASSERT(clock_class);
+ clock_value->clock_class = NULL;
+ bt_object_pool_recycle_object(&clock_class->cv_pool, clock_value);
+ bt_put(clock_class);
+}
+
+uint64_t bt_clock_value_get_value(struct bt_clock_value *clock_value)
+{
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
+ BT_ASSERT_PRE(clock_value->is_set,
+ "Clock value is not set: %!+k", clock_value);
+ return clock_value->value_cycles;
+}
+
+int bt_clock_value_get_ns_from_origin(struct bt_clock_value *clock_value,
+ int64_t *ret_value_ns)
+{
+ int ret = 0;
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
+ BT_ASSERT_PRE_NON_NULL(ret_value_ns, "Value (ns) (output)");
+ BT_ASSERT_PRE(clock_value->is_set,
+ "Clock value is not set: %!+k", clock_value);
+
+ if (clock_value->ns_from_origin_overflows) {
+ BT_LIB_LOGD("Clock value, once converted to nanoseconds from origin, "
+ "overflows the signed 64-bit integer range: "
+ "%![cv-]+k", clock_value);
+ ret = -1;
+ goto end;
+ }
+
+ *ret_value_ns = clock_value->ns_from_origin;
+
+end:
+ return ret;
+}
+
+struct bt_clock_class *bt_clock_value_borrow_clock_class(
+ struct bt_clock_value *clock_value)
+{
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
+ return clock_value->clock_class;
+}
#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/field-types.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/event-class.h>
#include <babeltrace/ctf-ir/event-class-internal.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/trace-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/resolve-field-path-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/ctf-ir/attributes-internal.h>
#include <babeltrace/compiler-internal.h>
#include <inttypes.h>
#include <stdlib.h>
-static inline
-void bt_event_class_finalize(struct bt_object *obj)
+#define BT_ASSERT_PRE_EVENT_CLASS_HOT(_ec) \
+ BT_ASSERT_PRE_HOT((_ec), "Event class", ": %!+E", (_ec))
+
+static
+void destroy_event_class(struct bt_object *obj)
{
- struct bt_event_class *event_class;
+ struct bt_event_class *event_class = (void *) obj;
- event_class = container_of(obj, struct bt_event_class, base);
- BT_LOGD("Finalizing event class: addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
+ BT_LIB_LOGD("Destroying event class: %!+E", event_class);
- if (event_class->name) {
- g_string_free(event_class->name, TRUE);
+ if (event_class->name.str) {
+ g_string_free(event_class->name.str, TRUE);
}
- if (event_class->emf_uri) {
- g_string_free(event_class->emf_uri, TRUE);
+ if (event_class->emf_uri.str) {
+ g_string_free(event_class->emf_uri.str, TRUE);
}
BT_LOGD_STR("Putting context field type.");
- bt_put(event_class->context_field_type);
+ bt_put(event_class->specific_context_ft);
BT_LOGD_STR("Putting payload field type.");
- bt_put(event_class->payload_field_type);
-}
-
-static inline
-int bt_event_class_initialize(struct bt_event_class *event_class,
- const char *name, bt_object_release_func release_func,
- bt_field_type_structure_create_func ft_struct_create_func)
-{
- int ret = 0;
-
- BT_LOGD("Initializing event class object: name=\"%s\"",
- name);
- bt_object_init_shared_with_parent(&event_class->base, release_func);
- event_class->payload_field_type = ft_struct_create_func();
- if (!event_class->payload_field_type) {
- BT_LOGE_STR("Cannot create event class's initial payload field type object.");
- goto error;
- }
-
- event_class->id = -1;
- event_class->name = g_string_new(name);
- if (!event_class->name) {
- BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
- }
-
- event_class->emf_uri = g_string_new(NULL);
- if (!event_class->emf_uri) {
- BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
- }
-
- event_class->log_level = BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
- BT_LOGD("Initialized event class object: addr=%p, name=\"%s\"",
- event_class, bt_event_class_get_name(event_class));
- return ret;
-
-error:
- ret = -1;
- return ret;
-}
-
-static
-void bt_event_class_destroy(struct bt_object *obj)
-{
- struct bt_event_class *event_class = (void *) obj;
-
- BT_LOGD("Destroying event class: addr=%p", obj);
- bt_event_class_finalize(obj);
+ bt_put(event_class->payload_ft);
bt_object_pool_finalize(&event_class->event_pool);
g_free(obj);
}
bt_event_destroy(event);
}
-struct bt_event_class *bt_event_class_create(const char *name)
+BT_ASSERT_PRE_FUNC
+static
+bool event_class_id_is_unique(struct bt_stream_class *stream_class, uint64_t id)
{
- int ret;
- struct bt_event_class *event_class = NULL;
+ uint64_t i;
+ bool is_unique = true;
- if (!name) {
- BT_LOGW_STR("Invalid parameter: name is NULL.");
- goto error;
+ for (i = 0; i < stream_class->event_classes->len; i++) {
+ struct bt_event_class *ec =
+ stream_class->event_classes->pdata[i];
+
+ if (ec->id == id) {
+ is_unique = false;
+ goto end;
+ }
}
- BT_LOGD("Creating event class object: name=\"%s\"",
- name);
+end:
+ return is_unique;
+}
+
+static
+struct bt_event_class *create_event_class_with_id(
+ struct bt_stream_class *stream_class, uint64_t id)
+{
+ int ret;
+ struct bt_event_class *event_class;
+
+ BT_ASSERT(stream_class);
+ BT_ASSERT_PRE(event_class_id_is_unique(stream_class, id),
+ "Duplicate event class ID: %![sc-]+S, id=%" PRIu64,
+ stream_class, id);
+ BT_LIB_LOGD("Creating event class object: %![sc-]+S, id=%" PRIu64,
+ stream_class, id);
event_class = g_new0(struct bt_event_class, 1);
if (!event_class) {
BT_LOGE_STR("Failed to allocate one event class.");
goto error;
}
- ret = bt_event_class_initialize(event_class,
- name, bt_event_class_destroy,
- (bt_field_type_structure_create_func)
- bt_field_type_structure_create);
- if (ret) {
- goto error;
+ bt_object_init_shared_with_parent(&event_class->base,
+ destroy_event_class);
+ event_class->id = id;
+ bt_property_uint_init(&event_class->log_level,
+ BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE, 0);
+ event_class->name.str = g_string_new(NULL);
+ if (!event_class->name.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ ret = -1;
+ goto end;
+ }
+
+ event_class->emf_uri.str = g_string_new(NULL);
+ if (!event_class->emf_uri.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ ret = -1;
+ goto end;
}
ret = bt_object_pool_initialize(&event_class->event_pool,
goto error;
}
- BT_LOGD("Created event class object: addr=%p, name=\"%s\"",
- event_class, bt_event_class_get_name(event_class));
+ bt_object_set_parent(&event_class->base, &stream_class->base);
+ g_ptr_array_add(stream_class->event_classes, event_class);
+ bt_stream_class_freeze(stream_class);
+ BT_LIB_LOGD("Created event class object: %!+E", event_class);
goto end;
error:
- bt_put(event_class);
+ BT_PUT(event_class);
end:
return event_class;
}
+struct bt_event_class *bt_event_class_create(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->assigns_automatic_event_class_id,
+ "Stream class does not automatically assigns event class IDs: "
+ "%![sc-]+S", stream_class);
+ return create_event_class_with_id(stream_class,
+ (uint64_t) stream_class->event_classes->len);
+}
+
+struct bt_event_class *bt_event_class_create_with_id(
+ struct bt_stream_class *stream_class, uint64_t id)
+{
+ BT_ASSERT_PRE(!stream_class->assigns_automatic_event_class_id,
+ "Stream class automatically assigns event class IDs: "
+ "%![sc-]+S", stream_class);
+ return create_event_class_with_id(stream_class, id);
+}
+
const char *bt_event_class_get_name(struct bt_event_class *event_class)
{
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- BT_ASSERT(event_class->name);
- return event_class->name->str;
+ return event_class->name.value;
}
-int64_t bt_event_class_get_id(struct bt_event_class *event_class)
+int bt_event_class_set_name(struct bt_event_class *event_class,
+ const char *name)
{
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- return event_class->id;
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class);
+ g_string_assign(event_class->name.str, name);
+ event_class->name.value = event_class->name.str->str;
+ BT_LIB_LOGV("Set event class's name: %!+E", event_class);
+ return 0;
}
-int bt_event_class_set_id(struct bt_event_class *event_class,
- uint64_t id_param)
+uint64_t bt_event_class_get_id(struct bt_event_class *event_class)
{
- int ret = 0;
- int64_t id = (int64_t) id_param;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (event_class->frozen) {
- BT_LOGW("Invalid parameter: event class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
-
- if (id < 0) {
- BT_LOGW("Invalid parameter: invalid event class's ID: "
- "addr=%p, name=\"%s\", id=%" PRIu64,
- event_class,
- bt_event_class_get_name(event_class),
- id_param);
- ret = -1;
- goto end;
- }
-
- event_class->id = id;
- BT_LOGV("Set event class's ID: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class), id);
-
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ return event_class->id;
}
-enum bt_event_class_log_level bt_event_class_get_log_level(
- struct bt_event_class *event_class)
+enum bt_property_availability bt_event_class_get_log_level(
+ struct bt_event_class *event_class,
+ enum bt_event_class_log_level *log_level)
{
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- return event_class->log_level;
+ BT_ASSERT_PRE_NON_NULL(log_level, "Log level (output)");
+ *log_level = (enum bt_event_class_log_level)
+ event_class->log_level.value;
+ return event_class->log_level.base.avail;
}
int bt_event_class_set_log_level(struct bt_event_class *event_class,
enum bt_event_class_log_level log_level)
{
- int ret = 0;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (event_class->frozen) {
- BT_LOGW("Invalid parameter: event class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
-
- switch (log_level) {
- case BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
- case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
- case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
- case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
- case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
- case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
- case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
- case BT_EVENT_CLASS_LOG_LEVEL_INFO:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
- case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
- break;
- default:
- BT_LOGW("Invalid parameter: unknown event class log level: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%d",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class), log_level);
- ret = -1;
- goto end;
- }
-
- event_class->log_level = log_level;
- BT_LOGV("Set event class's log level: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%s",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class),
- bt_common_event_class_log_level_string(log_level));
-
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class);
+ bt_property_uint_set(&event_class->log_level,
+ (uint64_t) log_level);
+ BT_LIB_LOGV("Set event class's log level: %!+E", event_class);
+ return 0;
}
const char *bt_event_class_get_emf_uri(struct bt_event_class *event_class)
{
- const char *emf_uri = NULL;
-
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-
- if (event_class->emf_uri->len > 0) {
- emf_uri = event_class->emf_uri->str;
- }
-
- return emf_uri;
+ return event_class->emf_uri.value;
}
int bt_event_class_set_emf_uri(struct bt_event_class *event_class,
const char *emf_uri)
{
- int ret = 0;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (emf_uri && strlen(emf_uri) == 0) {
- BT_LOGW_STR("Invalid parameter: EMF URI is empty.");
- ret = -1;
- goto end;
- }
-
- if (event_class->frozen) {
- BT_LOGW("Invalid parameter: event class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
-
- if (emf_uri) {
- g_string_assign(event_class->emf_uri, emf_uri);
- BT_LOGV("Set event class's EMF URI: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", emf-uri=\"%s\"",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class), emf_uri);
- } else {
- g_string_assign(event_class->emf_uri, "");
- BT_LOGV("Reset event class's EMF URI: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- }
-
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_ASSERT_PRE_NON_NULL(emf_uri, "EMF URI");
+ BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class);
+ g_string_assign(event_class->emf_uri.str, emf_uri);
+ event_class->emf_uri.value = event_class->emf_uri.str->str;
+ BT_LIB_LOGV("Set event class's EMF URI: %!+E", event_class);
+ return 0;
}
struct bt_stream_class *bt_event_class_borrow_stream_class(
struct bt_event_class *event_class)
{
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- return (void *) bt_object_borrow_parent(&event_class->base);
+ return bt_event_class_borrow_stream_class_inline(event_class);
}
-struct bt_field_type *bt_event_class_borrow_payload_field_type(
+struct bt_field_type *bt_event_class_borrow_specific_context_field_type(
struct bt_event_class *event_class)
{
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- return event_class->payload_field_type;
+ return event_class->specific_context_ft;
}
-int bt_event_class_set_payload_field_type(struct bt_event_class *event_class,
+int bt_event_class_set_specific_context_field_type(
+ struct bt_event_class *event_class,
struct bt_field_type *field_type)
{
- int ret = 0;
+ int ret;
+ struct bt_stream_class *stream_class;
+ struct bt_trace *trace;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = NULL,
+ .packet_context = NULL,
+ .event_header = NULL,
+ .event_common_context = NULL,
+ .event_specific_context = field_type,
+ .event_payload = NULL,
+ };
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Specific context field type is not a structure field type: "
+ "%!+F", field_type);
+ stream_class = bt_event_class_borrow_stream_class_inline(
+ event_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
+ resolve_ctx.packet_header = trace->packet_header_ft;
+ resolve_ctx.packet_context = stream_class->packet_context_ft;
+ resolve_ctx.event_header = stream_class->event_header_ft;
+ resolve_ctx.event_common_context =
+ stream_class->event_common_context_ft;
+
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
goto end;
}
- if (field_type && bt_field_type_get_type_id(field_type) !=
- BT_FIELD_TYPE_ID_STRUCT) {
- BT_LOGW("Invalid parameter: event class's payload field type must be a structure: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "payload-ft-addr=%p, payload-ft-id=%s",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class), field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(field_type)));
- ret = -1;
- goto end;
- }
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(event_class->specific_context_ft);
+ event_class->specific_context_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set event class's specific context field type: %!+E",
+ event_class);
- bt_put(event_class->payload_field_type);
- event_class->payload_field_type = bt_get(field_type);
- BT_LOGV("Set event class's payload field type: "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", payload-ft-addr=%p",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class), field_type);
end:
return ret;
}
-struct bt_field_type *bt_event_class_borrow_context_field_type(
+struct bt_field_type *bt_event_class_borrow_payload_field_type(
struct bt_event_class *event_class)
{
- struct bt_field_type *context_ft = NULL;
-
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-
- if (!event_class->context_field_type) {
- BT_LOGV("Event class has no context field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- goto end;
- }
-
- context_ft = event_class->context_field_type;
-
-end:
- return context_ft;
+ return event_class->payload_ft;
}
-int bt_event_class_set_context_field_type(
- struct bt_event_class *event_class,
+int bt_event_class_set_payload_field_type(struct bt_event_class *event_class,
struct bt_field_type *field_type)
{
- int ret = 0;
-
- if (!event_class) {
- BT_LOGW_STR("Invalid parameter: event class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (event_class->frozen) {
- BT_LOGW("Invalid parameter: event class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- ret = -1;
- goto end;
- }
+ int ret;
+ struct bt_stream_class *stream_class;
+ struct bt_trace *trace;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = NULL,
+ .packet_context = NULL,
+ .event_header = NULL,
+ .event_common_context = NULL,
+ .event_specific_context = NULL,
+ .event_payload = field_type,
+ };
- if (field_type && bt_field_type_get_type_id(field_type) !=
- BT_FIELD_TYPE_ID_STRUCT) {
- BT_LOGW("Invalid parameter: event class's context field type must be a structure: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "context-ft-id=%s",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class),
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(field_type)));
- ret = -1;
+ BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_EVENT_CLASS_HOT(event_class);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Payload field type is not a structure field type: %!+F",
+ field_type);
+ stream_class = bt_event_class_borrow_stream_class_inline(
+ event_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
+ resolve_ctx.packet_header = trace->packet_header_ft;
+ resolve_ctx.packet_context = stream_class->packet_context_ft;
+ resolve_ctx.event_header = stream_class->event_header_ft;
+ resolve_ctx.event_common_context =
+ stream_class->event_common_context_ft;
+ resolve_ctx.event_specific_context = event_class->specific_context_ft;
+
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
goto end;
}
- bt_put(event_class->context_field_type);
- event_class->context_field_type = bt_get(field_type);
- BT_LOGV("Set event class's context field type: "
- "event-class-addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64 ", context-ft-addr=%p",
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class), field_type);
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(event_class->payload_ft);
+ event_class->payload_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set event class's payload field type: %!+E", event_class);
end:
return ret;
}
BT_HIDDEN
-void bt_event_class_freeze(struct bt_event_class *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_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- event_class->frozen = 1;
- BT_LOGD_STR("Freezing event class's context field type.");
- bt_field_type_freeze(event_class->context_field_type);
- BT_LOGD_STR("Freezing event class's payload field type.");
- bt_field_type_freeze(event_class->payload_field_type);
-}
-
-BT_HIDDEN
-int bt_event_class_validate_single_clock_class(
- struct bt_event_class *event_class,
- struct bt_clock_class **expected_clock_class)
+void _bt_event_class_freeze(struct bt_event_class *event_class)
{
- int ret = 0;
-
+ /* The field types are already frozen */
BT_ASSERT(event_class);
- BT_ASSERT(expected_clock_class);
- ret = bt_field_type_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_event_class_get_name(event_class),
- event_class->id,
- event_class->context_field_type);
- goto end;
- }
-
- ret = bt_field_type_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_event_class_get_name(event_class),
- event_class->id,
- event_class->payload_field_type);
- goto end;
- }
-
-end:
- return ret;
+ BT_LIB_LOGD("Freezing event class: %!+E", event_class);
+ event_class->frozen = true;
}
#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/ctf-ir/event-header-field.h>
+#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <glib.h>
struct bt_field_wrapper *field_wrapper = (void *) header_field;
BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
- BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
- "Event header field's field object");
return (void *) field_wrapper->field;
}
*/
bt_field_wrapper_destroy(field_wrapper);
}
+
+struct bt_event_header_field *bt_event_header_field_create(
+ struct bt_stream_class *stream_class)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(bt_stream_class_borrow_trace_inline(stream_class),
+ "Stream class is not part of a trace: %!+S", stream_class);
+ BT_ASSERT_PRE(stream_class->event_header_ft,
+ "Stream class has no event header field type: %!+S",
+ stream_class);
+ field_wrapper = bt_field_wrapper_create(
+ &stream_class->event_header_field_pool,
+ (void *) stream_class->event_header_ft);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
+ "%![sc-]+S", stream_class);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ bt_stream_class_freeze(stream_class);
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
#include <babeltrace/ctf-ir/packet-internal.h>
#include <babeltrace/ctf-ir/trace.h>
#include <babeltrace/ctf-ir/trace-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
#include <babeltrace/ctf-ir/packet-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ref.h>
#include <babeltrace/assert-internal.h>
#include <inttypes.h>
-static inline
-int bt_event_validate_types_for_create(
- struct bt_event_class *event_class,
- struct bt_validation_output *validation_output,
- bt_validation_flag_copy_field_type_func copy_field_type_func)
-{
- int ret;
- enum bt_validation_flag validation_flags =
- BT_VALIDATION_FLAG_STREAM |
- BT_VALIDATION_FLAG_EVENT;
- struct bt_trace *trace = NULL;
- struct bt_stream_class *stream_class = NULL;
- struct bt_field_type *packet_header_type = NULL;
- struct bt_field_type *packet_context_type = NULL;
- struct bt_field_type *event_header_type = NULL;
- struct bt_field_type *stream_event_ctx_type = NULL;
- struct bt_field_type *event_context_type = NULL;
- struct bt_field_type *event_payload_type = NULL;
- int trace_valid = 0;
- struct bt_value *environment = NULL;
-
- stream_class = bt_event_class_borrow_stream_class(event_class);
- BT_ASSERT(stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
- if (trace) {
- BT_LOGD_STR("Event class is part of a trace.");
- packet_header_type =
- bt_trace_borrow_packet_header_field_type(trace);
- trace_valid = trace->valid;
- BT_ASSERT(trace_valid);
- environment = trace->environment;
- }
-
- packet_context_type =
- bt_stream_class_borrow_packet_context_field_type(
- stream_class);
- event_header_type =
- bt_stream_class_borrow_event_header_field_type(
- stream_class);
- stream_event_ctx_type =
- bt_stream_class_borrow_event_context_field_type(
- stream_class);
- event_context_type =
- bt_event_class_borrow_context_field_type(event_class);
- event_payload_type =
- bt_event_class_borrow_payload_field_type(event_class);
- ret = bt_validate_class_types(environment, packet_header_type,
- packet_context_type, event_header_type, stream_event_ctx_type,
- event_context_type, event_payload_type, trace_valid,
- stream_class->valid, event_class->valid,
- validation_output, validation_flags, 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_validation_output_put_types(validation_output);
- ret = -1;
-
-end:
- return ret;
-}
-
-static
-int bt_event_create_fields(
- struct bt_stream_class *stream_class,
- struct bt_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_field_wrapper **header_field,
- struct bt_field **stream_event_context_field,
- struct bt_field **context_field,
- struct bt_field **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_event_validate(struct bt_event *event)
+void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen)
{
- int ret = 0;
- struct bt_stream_class *stream_class;
-
BT_ASSERT(event);
- if (event->header_field) {
- ret = bt_field_validate_recursive(
- event->header_field->field);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid event's header field: "
- "%![event-]+e, %![field-]+f",
- event, event->header_field->field);
- goto end;
- }
- }
-
- stream_class = bt_event_class_borrow_stream_class(event->class);
-
- /*
- * We should not have been able to create the event without associating
- * the event class to a stream class.
- */
- BT_ASSERT(stream_class);
-
- if (stream_class->event_context_field_type) {
- ret = bt_field_validate_recursive(
- event->stream_event_context_field);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid event's stream event context field: "
- "%![event-]+e, %![field-]+f",
- event, event->stream_event_context_field);
- goto end;
- }
- }
-
- if (event->class->context_field_type) {
- ret = bt_field_validate_recursive(event->context_field);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid event's payload field: "
- "%![event-]+e, %![field-]+f",
- event, event->context_field);
- goto end;
- }
- }
-
- ret = bt_field_validate_recursive(event->payload_field);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid event's payload field: "
- "%![event-]+e, %![field-]+f",
- event, event->payload_field);
- goto end;
- }
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-void _bt_event_set_is_frozen(struct bt_event *event,
- bool is_frozen)
-{
- BT_ASSERT(event);
- BT_LOGD("Freezing event: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
+ BT_LIB_LOGD("Setting event's frozen state: %!+e, is-frozen=%d",
+ event, is_frozen);
if (event->header_field) {
- BT_LOGD_STR("Freezing event's header field.");
- bt_field_set_is_frozen_recursive(
+ BT_LOGD_STR("Setting event's header field's frozen state.");
+ bt_field_set_is_frozen(
event->header_field->field, is_frozen);
}
- if (event->stream_event_context_field) {
- BT_LOGD_STR("Freezing event's stream event context field.");
- bt_field_set_is_frozen_recursive(
- event->stream_event_context_field, is_frozen);
+ if (event->common_context_field) {
+ BT_LOGD_STR("Setting event's common context field's frozen state.");
+ bt_field_set_is_frozen(
+ event->common_context_field, is_frozen);
}
- if (event->context_field) {
- BT_LOGD_STR("Freezing event's context field.");
- bt_field_set_is_frozen_recursive(event->context_field,
+ if (event->specific_context_field) {
+ BT_LOGD_STR("Setting event's specific context field's frozen state.");
+ bt_field_set_is_frozen(event->specific_context_field,
is_frozen);
}
if (event->payload_field) {
- BT_LOGD_STR("Freezing event's payload field.");
- bt_field_set_is_frozen_recursive(event->payload_field,
+ BT_LOGD_STR("Setting event's payload field's frozen state.");
+ bt_field_set_is_frozen(event->payload_field,
is_frozen);
}
event->frozen = is_frozen;
- BT_LOGD_STR("Freezing event's packet.");
+ BT_LOGD_STR("Setting event's packet's frozen state.");
bt_packet_set_is_frozen(event->packet, is_frozen);
}
-static inline
-int bt_event_initialize(struct bt_event *event,
- struct bt_event_class *event_class,
- bt_validation_flag_copy_field_type_func field_type_copy_func,
- 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_trace *trace = NULL;
- struct bt_stream_class *stream_class = NULL;
- struct bt_field_wrapper *event_header = NULL;
- struct bt_field *stream_event_context = NULL;
- struct bt_field *event_context = NULL;
- struct bt_field *event_payload = NULL;
- struct bt_validation_output validation_output = { 0 };
- struct bt_clock_class *expected_clock_class = NULL;
-
- BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
- BT_LOGD("Initializing event object: event-class-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event_class, bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
-
- stream_class = bt_event_class_borrow_stream_class(event_class);
- BT_ASSERT_PRE(stream_class,
- "Event class is not part of a stream class: %!+E", event_class);
-
- /* The event class was frozen when added to its stream class */
- BT_ASSERT(event_class->frozen);
- trace = bt_stream_class_borrow_trace(stream_class);
- BT_ASSERT_PRE(trace,
- "Event class's stream class is not part of a trace: "
- "%![ec-]+E, %![ec-]+S", event_class, stream_class);
-
- /*
- * This must be called before anything that can fail because on
- * failure, the caller releases the reference to `event` to
- * destroy it.
- */
- bt_object_init_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_stream_class_validate_single_clock_class(
- stream_class, &expected_clock_class);
- if (ret) {
- BT_LOGW("Event class's stream class or one of its event "
- "classes contains a field type which is not "
- "recursively mapped to the expected "
- "clock class: "
- "stream-class-addr=%p, "
- "stream-class-id=%" PRId64 ", "
- "stream-class-name=\"%s\", "
- "expected-clock-class-addr=%p, "
- "expected-clock-class-name=\"%s\"",
- stream_class,
- bt_stream_class_get_id(stream_class),
- bt_stream_class_get_name(stream_class),
- expected_clock_class,
- expected_clock_class ?
- bt_clock_class_get_name(expected_clock_class) :
- NULL);
- goto error;
- }
- }
-
- /* Validate the trace, the stream class, and the event class */
- ret = bt_event_validate_types_for_create(
- event_class, &validation_output, field_type_copy_func);
- if (ret) {
- /* bt_event_validate_types_for_create() logs errors */
- 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.
- *
- * TODO: Is this still true now that this API and CTF writer are
- * two different implementations?
- */
- event->class = bt_get(event_class);
- ret = bt_event_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_event_create_fields() logs errors */
- goto error;
- }
-
- /*
- * At this point all the fields are created, potentially from
- * validated copies of field types, so that the field types and
- * fields can be replaced in the trace, stream class,
- * event class, and created event.
- */
- bt_validation_replace_types(trace, stream_class, event_class,
- &validation_output,
- BT_VALIDATION_FLAG_STREAM | BT_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_validation_replace_types().
- */
- bt_validation_output_put_types(&validation_output);
-
- /*
- * Freeze the stream class since the event header must not be changed
- * anymore.
- */
- bt_stream_class_freeze(stream_class);
-
- /*
- * It is safe to set the stream class's unique clock class
- * now because the stream class is frozen.
- */
- if (expected_clock_class) {
- BT_MOVE(stream_class->clock_class, expected_clock_class);
- }
-
- /*
- * Mark stream class, and event class as valid since
- * they're all frozen now.
- */
- stream_class->valid = 1;
- event_class->valid = 1;
-
- /* Put stuff we borrowed from the event class */
- BT_LOGD("Initialized event object: addr=%p, event-class-name=\"%s\", "
- "event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
-
-error:
- bt_validation_output_put_types(&validation_output);
- bt_put(expected_clock_class);
-
- if (event_header) {
- release_header_field_func(event_header, stream_class);
- }
-
- if (stream_event_context) {
- release_field_func(stream_event_context);
- }
-
- if (event_context) {
- release_field_func(event_context);
- }
-
- if (event_payload) {
- release_field_func(event_payload);
- }
-
- ret = -1;
-
-end:
- return ret;
-}
-
static
-void bt_event_header_field_recycle(struct bt_field_wrapper *field_wrapper,
+void recycle_event_header_field(struct bt_field_wrapper *field_wrapper,
struct bt_stream_class *stream_class)
{
BT_ASSERT(field_wrapper);
field_wrapper);
}
-static
+static inline
struct bt_field_wrapper *create_event_header_field(
- struct bt_stream_class *stream_class,
- struct bt_field_type *ft)
+ struct bt_stream_class *stream_class)
{
struct bt_field_wrapper *field_wrapper = NULL;
field_wrapper = bt_field_wrapper_create(
- &stream_class->event_header_field_pool, (void *) ft);
+ &stream_class->event_header_field_pool,
+ bt_stream_class_borrow_event_header_field_type(stream_class));
if (!field_wrapper) {
goto error;
}
error:
if (field_wrapper) {
- bt_event_header_field_recycle(field_wrapper, stream_class);
+ recycle_event_header_field(field_wrapper, stream_class);
field_wrapper = NULL;
}
BT_HIDDEN
struct bt_event *bt_event_new(struct bt_event_class *event_class)
{
- int ret;
struct bt_event *event = NULL;
struct bt_stream_class *stream_class;
+ struct bt_field_type *ft;
+ BT_ASSERT(event_class);
event = g_new0(struct bt_event, 1);
if (!event) {
BT_LOGE_STR("Failed to allocate one event.");
goto error;
}
- ret = bt_event_initialize(event, event_class,
- (bt_validation_flag_copy_field_type_func) bt_field_type_copy,
- (create_field_func) bt_field_create_recursive,
- (release_field_func) bt_field_destroy_recursive,
- (create_header_field_func) create_event_header_field,
- (release_header_field_func) bt_event_header_field_recycle);
- if (ret) {
- /* bt_event_initialize() logs errors */
- goto error;
- }
-
+ bt_object_init_unique(&event->base);
stream_class = bt_event_class_borrow_stream_class(event_class);
BT_ASSERT(stream_class);
- ret = bt_clock_value_set_initialize(&event->cv_set);
- if (ret) {
- goto error;
+
+ if (bt_stream_class_borrow_event_header_field_type(stream_class)) {
+ event->header_field = create_event_header_field(stream_class);
+ if (!event->header_field) {
+ BT_LOGE_STR("Cannot create event header field.");
+ goto error;
+ }
+ }
+
+ ft = bt_stream_class_borrow_event_common_context_field_type(
+ stream_class);
+ if (ft) {
+ event->common_context_field = bt_field_create(ft);
+ if (!event->common_context_field) {
+ /* bt_field_create() logs errors */
+ goto error;
+ }
+ }
+
+ ft = bt_event_class_borrow_specific_context_field_type(event_class);
+ if (ft) {
+ event->specific_context_field = bt_field_create(ft);
+ if (!event->specific_context_field) {
+ /* bt_field_create() logs errors */
+ goto error;
+ }
+ }
+
+ ft = bt_event_class_borrow_payload_field_type(event_class);
+ if (ft) {
+ event->payload_field = bt_field_create(ft);
+ if (!event->payload_field) {
+ /* bt_field_create() logs errors */
+ goto error;
+ }
+ }
+
+ if (stream_class->default_clock_class) {
+ event->default_cv = bt_clock_value_create(
+ stream_class->default_clock_class);
+ if (!event->default_cv) {
+ /* bt_clock_value_create() logs errors */
+ goto error;
+ }
}
goto end;
return event->packet ? event->packet->stream : NULL;
}
-struct bt_field *bt_event_borrow_payload(struct bt_event *event)
+struct bt_field *bt_event_borrow_header_field(struct bt_event *event)
{
- struct bt_field *payload = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
-
- if (!event->payload_field) {
- BT_LOGV("Event has no current payload field: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
- }
-
- payload = event->payload_field;
-
-end:
- return payload;
+ return event->header_field ? event->header_field->field : NULL;
}
-struct bt_field *bt_event_borrow_header(struct bt_event *event)
+struct bt_field *bt_event_borrow_common_context_field(struct bt_event *event)
{
- struct bt_field *header = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
-
- if (!event->header_field) {
- BT_LOGV("Event has no current header field: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
- }
-
- header = event->header_field->field;
-
-end:
- return header;
+ return event->common_context_field;
}
-struct bt_field *bt_event_borrow_context(struct bt_event *event)
+struct bt_field *bt_event_borrow_specific_context_field(struct bt_event *event)
{
- struct bt_field *context = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
-
- if (!event->context_field) {
- BT_LOGV("Event has no current context field: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
- }
-
- context = event->context_field;
-
-end:
- return context;
+ return event->specific_context_field;
}
-struct bt_field *bt_event_borrow_stream_event_context(
- struct bt_event *event)
+struct bt_field *bt_event_borrow_payload_field(struct bt_event *event)
{
- struct bt_field *stream_event_context = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
-
- if (!event->stream_event_context_field) {
- BT_LOGV("Event has no current stream event context field: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
- }
-
- stream_event_context = event->stream_event_context_field;
-
-end:
- return stream_event_context;
+ return event->payload_field;
}
static
void release_event_header_field(struct bt_field_wrapper *field_wrapper,
struct bt_event *event)
{
- struct bt_event_class *event_class = bt_event_borrow_class(event);
-
- if (!event_class) {
+ if (!event->class) {
bt_field_wrapper_destroy(field_wrapper);
} else {
struct bt_stream_class *stream_class =
- bt_event_class_borrow_stream_class(event_class);
+ bt_event_class_borrow_stream_class(event->class);
BT_ASSERT(stream_class);
- bt_event_header_field_recycle(field_wrapper, stream_class);
+ recycle_event_header_field(field_wrapper, stream_class);
}
}
-static inline
-void bt_event_finalize(struct bt_object *obj,
- void (*field_release_func)(void *),
- void (*header_field_release_func)(void *, struct bt_event *))
+BT_HIDDEN
+void bt_event_destroy(struct bt_event *event)
{
- struct bt_event *event = (void *) obj;
-
- BT_LOGD("Destroying event: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event,
- event->class ? bt_event_class_get_name(event->class) : NULL,
- event->class ? bt_event_class_get_id(event->class) : INT64_C(-1));
+ BT_ASSERT(event);
+ BT_LIB_LOGD("Destroying event: %!+e", event);
if (event->header_field) {
BT_LOGD_STR("Releasing event's header field.");
- header_field_release_func(event->header_field, event);
+ release_event_header_field(event->header_field, event);
}
- if (event->stream_event_context_field) {
- BT_LOGD_STR("Releasing event's stream event context field.");
- field_release_func(event->stream_event_context_field);
+ if (event->common_context_field) {
+ BT_LOGD_STR("Destroying event's stream event context field.");
+ bt_field_destroy(event->common_context_field);
}
- if (event->context_field) {
- BT_LOGD_STR("Releasing event's context field.");
- field_release_func(event->context_field);
+ if (event->specific_context_field) {
+ BT_LOGD_STR("Destroying event's context field.");
+ bt_field_destroy(event->specific_context_field);
}
if (event->payload_field) {
- BT_LOGD_STR("Releasing event's payload field.");
- field_release_func(event->payload_field);
+ BT_LOGD_STR("Destroying event's payload field.");
+ bt_field_destroy(event->payload_field);
}
- /*
- * Leave this after calling header_field_release_func() because
- * this function receives the event object and could need its
- * class to perform some cleanup.
- */
- if (!event->base.parent) {
- /*
- * Event was keeping a reference to its class since it shared no
- * common ancestor with it to guarantee they would both have the
- * same lifetime.
- */
- bt_put(event->class);
+ BT_LOGD_STR("Putting event's class.");
+ bt_put(event->class);
+
+ if (event->default_cv) {
+ bt_clock_value_recycle(event->default_cv);
}
-}
-BT_HIDDEN
-void bt_event_destroy(struct bt_event *event)
-{
- BT_ASSERT(event);
- bt_event_finalize((void *) event,
- (void *) bt_field_destroy_recursive,
- (void *) release_event_header_field);
- bt_clock_value_set_finalize(&event->cv_set);
BT_LOGD_STR("Putting event's packet.");
bt_put(event->packet);
g_free(event);
}
-int bt_event_set_clock_value(struct bt_event *event,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default)
+int bt_event_set_default_clock_value(struct bt_event *event,
+ uint64_t value_cycles)
{
+ struct bt_stream_class *sc;
+
BT_ASSERT_PRE_NON_NULL(event, "Event");
- BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
- BT_ASSERT_PRE_HOT(event, "Event", ": %!+e", event);
- BT_ASSERT_PRE(is_default,
- "You can only set a default clock value as of this version.");
- return bt_clock_value_set_set_clock_value(&event->cv_set, clock_class,
- raw_value, is_default);
+ BT_ASSERT_PRE_EVENT_HOT(event);
+ sc = bt_event_class_borrow_stream_class_inline(event->class);
+ BT_ASSERT(sc);
+ BT_ASSERT_PRE(sc->default_clock_class,
+ "Event's stream class has no default clock class: "
+ "%![ev-]+e, %![sc-]+S", event, sc);
+ BT_ASSERT(event->default_cv);
+ bt_clock_value_set_value_inline(event->default_cv, value_cycles);
+ BT_LIB_LOGV("Set event's default clock value: %![event-]+e, "
+ "value=%" PRIu64, event, value_cycles);
+ return 0;
}
-struct bt_clock_value *bt_event_borrow_default_clock_value(
- struct bt_event *event)
+enum bt_clock_value_status bt_event_borrow_default_clock_value(
+ struct bt_event *event, struct bt_clock_value **clock_value)
{
- struct bt_clock_value *clock_value = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
- clock_value = event->cv_set.default_cv;
- if (!clock_value) {
- BT_LIB_LOGV("No default clock value: %![event-]+e", event);
- }
-
- return clock_value;
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)");
+ *clock_value = event->default_cv;
+ return BT_CLOCK_VALUE_STATUS_KNOWN;
}
struct bt_packet *bt_event_borrow_packet(struct bt_event *event)
{
- struct bt_packet *packet = NULL;
-
BT_ASSERT_PRE_NON_NULL(event, "Event");
- if (!event->packet) {
- BT_LOGV("Event has no current packet: addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- event, bt_event_class_get_name(event->class),
- bt_event_class_get_id(event->class));
- goto end;
- }
-
- packet = event->packet;
-
-end:
- return packet;
+ return event->packet;
}
int bt_event_move_header(struct bt_event *event,
BT_ASSERT_PRE_NON_NULL(event, "Event");
BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field");
- BT_ASSERT_PRE_HOT(event, "Event", ": %!+e", event);
- stream_class = bt_event_class_borrow_stream_class(
- bt_event_borrow_class(event));
- BT_ASSERT_PRE(stream_class->event_header_field_type,
+ BT_ASSERT_PRE_EVENT_HOT(event);
+ stream_class = bt_event_class_borrow_stream_class_inline(event->class);
+ BT_ASSERT_PRE(stream_class->event_header_ft,
"Stream class has no event header field type: %!+S",
stream_class);
/* Recycle current header field: always exists */
BT_ASSERT(event->header_field);
- bt_event_header_field_recycle(event->header_field,
- stream_class);
+ recycle_event_header_field(event->header_field, stream_class);
/* Move new field */
- event->header_field = (void *) field_wrapper;
+ event->header_field = field_wrapper;
return 0;
}
#define BT_LOG_TAG "FIELD-PATH"
#include <babeltrace/lib-logging-internal.h>
+#include <babeltrace/assert-pre-internal.h>
#include <babeltrace/ctf-ir/field-types.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/field-path-internal.h>
#include <glib.h>
static
-void field_path_destroy(struct bt_object *obj)
+void destroy_field_path(struct bt_object *obj)
{
struct bt_field_path *field_path = (struct bt_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);
- }
+ BT_ASSERT(field_path);
+ BT_LIB_LOGD("Destroying field path: %!+P", field_path);
+ g_array_free(field_path->indexes, TRUE);
g_free(field_path);
}
goto error;
}
- bt_object_init_shared(&field_path->base, field_path_destroy);
- field_path->root = BT_SCOPE_UNKNOWN;
- field_path->indexes = g_array_new(TRUE, FALSE, sizeof(int));
+ bt_object_init_shared(&field_path->base, destroy_field_path);
+ field_path->indexes = g_array_new(FALSE, FALSE, sizeof(uint64_t));
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;
+ BT_LIB_LOGD("Created empty field path object: %!+P", field_path);
+ goto end;
error:
BT_PUT(field_path);
- return NULL;
-}
-BT_HIDDEN
-void bt_field_path_clear(struct bt_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_field_path *bt_field_path_copy(
- struct bt_field_path *path)
-{
- struct bt_field_path *new_path;
-
- BT_ASSERT(path);
- BT_LOGD("Copying field path: addr=%p, index-count=%u",
- path, path->indexes->len);
- new_path = bt_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;
+ return field_path;
}
-enum bt_scope bt_field_path_get_root_scope(
- const struct bt_field_path *field_path)
+enum bt_scope bt_field_path_get_root_scope(struct bt_field_path *field_path)
{
- enum bt_scope scope = BT_SCOPE_UNKNOWN;
-
- if (!field_path) {
- BT_LOGW_STR("Invalid parameter: field path is NULL.");
- goto end;
- }
-
- scope = field_path->root;
-
-end:
- return scope;
+ BT_ASSERT_PRE_NON_NULL(field_path, "Field path");
+ return field_path->root;
}
-int64_t bt_field_path_get_index_count(
- const struct bt_field_path *field_path)
+uint64_t bt_field_path_get_index_count(struct bt_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;
+ BT_ASSERT_PRE_NON_NULL(field_path, "Field path");
+ return (uint64_t) field_path->indexes->len;
}
-int bt_field_path_get_index(const struct bt_field_path *field_path,
+uint64_t bt_field_path_get_index_by_index(struct bt_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;
+ BT_ASSERT_PRE_NON_NULL(field_path, "Field path");
+ BT_ASSERT_PRE_VALID_INDEX(index, field_path->indexes->len);
+ return bt_field_path_get_index_by_index_inline(field_path, index);
}
#include <babeltrace/compiler-internal.h>
#include <babeltrace/endian-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/compat/glib-internal.h>
#include <float.h>
#include <inttypes.h>
#include <stdlib.h>
-static
-struct bt_field_type *bt_field_type_integer_copy(
- struct bt_field_type *ft);
+enum bt_field_type_id bt_field_type_get_type_id(struct bt_field_type *ft)
+{
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ return ft->id;
+}
static
-struct bt_field_type *bt_field_type_enumeration_copy_recursive(
- struct bt_field_type *ft);
+void init_field_type(struct bt_field_type *ft, enum bt_field_type_id id,
+ bt_object_release_func release_func)
+{
+ BT_ASSERT(ft);
+ BT_ASSERT(bt_field_type_has_known_id(ft));
+ BT_ASSERT(release_func);
+ bt_object_init_shared(&ft->base, release_func);
+ ft->id = id;
+}
static
-struct bt_field_type *bt_field_type_floating_point_copy(
- struct bt_field_type *ft);
+void init_integer_field_type(struct bt_field_type_integer *ft, enum bt_field_type_id id,
+ bt_object_release_func release_func)
+{
+ init_field_type((void *) ft, id, release_func);
+ ft->range = 64;
+ ft->base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
+}
static
-struct bt_field_type *bt_field_type_structure_copy_recursive(
- struct bt_field_type *ft);
+void destroy_integer_field_type(struct bt_object *obj)
+{
+ BT_ASSERT(obj);
+ BT_LIB_LOGD("Destroying integer field type object: %!+F", obj);
+ g_free(obj);
+}
-static
-struct bt_field_type *bt_field_type_variant_copy_recursive(
- struct bt_field_type *ft);
+static inline
+struct bt_field_type *create_integer_field_type(enum bt_field_type_id id)
+{
+ struct bt_field_type_integer *int_ft = NULL;
-static
-struct bt_field_type *bt_field_type_array_copy_recursive(
- struct bt_field_type *ft);
+ BT_LOGD("Creating default integer field type object: id=%s",
+ bt_common_field_type_id_string(id));
+ int_ft = g_new0(struct bt_field_type_integer, 1);
+ if (!int_ft) {
+ BT_LOGE_STR("Failed to allocate one integer field type.");
+ goto error;
+ }
-static
-struct bt_field_type *bt_field_type_sequence_copy_recursive(
- struct bt_field_type *type);
+ init_integer_field_type(int_ft, id, destroy_integer_field_type);
+ BT_LIB_LOGD("Created integer field type object: %!+F", int_ft);
+ goto end;
-static
-struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft);
+error:
+ BT_PUT(int_ft);
-static
-int bt_field_type_integer_validate(struct bt_field_type *ft);
+end:
+ return (void *) int_ft;
+}
-static
-int bt_field_type_enumeration_validate_recursive(
- struct bt_field_type *ft);
-static
-int bt_field_type_sequence_validate_recursive(
- struct bt_field_type *ft);
-static
-int bt_field_type_array_validate_recursive(
- struct bt_field_type *ft);
-static
-int bt_field_type_structure_validate_recursive(
- struct bt_field_type *ft);
-static
-int bt_field_type_variant_validate_recursive(
- struct bt_field_type *ft);
+struct bt_field_type *bt_field_type_unsigned_integer_create(void)
+{
+ return create_integer_field_type(BT_FIELD_TYPE_ID_UNSIGNED_INTEGER);
+}
-static
-void bt_field_type_generic_freeze(struct bt_field_type *ft);
+struct bt_field_type *bt_field_type_signed_integer_create(void)
+{
+ return create_integer_field_type(BT_FIELD_TYPE_ID_SIGNED_INTEGER);
+}
-static
-void bt_field_type_enumeration_freeze_recursive(
- struct bt_field_type *ft);
-static
-void bt_field_type_structure_freeze_recursive(
- struct bt_field_type *ft);
-static
-void bt_field_type_variant_freeze_recursive(
- struct bt_field_type *ft);
-static
-void bt_field_type_array_freeze_recursive(
- struct bt_field_type *ft);
-static
-void bt_field_type_sequence_freeze_recursive(
- struct bt_field_type *ft);
+uint64_t bt_field_type_integer_get_field_value_range(
+ struct bt_field_type *ft)
+{
+ struct bt_field_type_integer *int_ft = (void *) ft;
-static
-void bt_field_type_integer_set_byte_order(
- struct bt_field_type *ft, enum bt_byte_order byte_order);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_INT(ft, "Field type");
+ return int_ft->range;
+}
+BT_ASSERT_PRE_FUNC
static
-void bt_field_type_enumeration_set_byte_order_recursive(
- struct bt_field_type *ft, enum bt_byte_order byte_order);
+bool size_is_valid_for_enumeration_field_type(struct bt_field_type *ft,
+ uint64_t size)
+{
+ // TODO
+ return true;
+}
-static
-void bt_field_type_floating_point_set_byte_order(
- struct bt_field_type *ft, enum bt_byte_order byte_order);
+int bt_field_type_integer_set_field_value_range(
+ struct bt_field_type *ft, uint64_t size)
+{
+ struct bt_field_type_integer *int_ft = (void *) ft;
-static
-void bt_field_type_structure_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order);
-static
-void bt_field_type_variant_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_INT(ft, "Field type");
+ BT_ASSERT_PRE_FT_HOT(ft, "Field type");
+ BT_ASSERT_PRE(size <= 64,
+ "Unsupported size for integer field type's field value range "
+ "(maximum is 64): size=%" PRIu64, size);
+ BT_ASSERT_PRE(int_ft->common.id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER ||
+ int_ft->common.id == BT_FIELD_TYPE_ID_SIGNED_INTEGER ||
+ size_is_valid_for_enumeration_field_type(ft, size),
+ "Invalid field value range for enumeration field type: "
+ "at least one of the current mapping ranges contains values "
+ "which are outside this range: %!+F, size=%" PRIu64, ft, size);
+ int_ft->range = size;
+ BT_LIB_LOGV("Set integer field type's field value range: %!+F", ft);
+ return 0;
+}
-static
-void bt_field_type_array_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order);
+enum bt_field_type_integer_preferred_display_base
+bt_field_type_integer_get_preferred_display_base(struct bt_field_type *ft)
+{
+ struct bt_field_type_integer *int_ft = (void *) ft;
-static
-void bt_field_type_sequence_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_INT(ft, "Field type");
+ return int_ft->base;
+}
-static
-int bt_field_type_integer_compare(struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+int bt_field_type_integer_set_preferred_display_base(struct bt_field_type *ft,
+ enum bt_field_type_integer_preferred_display_base base)
+{
+ struct bt_field_type_integer *int_ft = (void *) ft;
-static
-int bt_field_type_floating_point_compare(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_INT(ft, "Field type");
+ BT_ASSERT_PRE_FT_HOT(ft, "Field type");
+ int_ft->base = base;
+ BT_LIB_LOGV("Set integer field type's preferred display base: %!+F", ft);
+ return 0;
+}
static
-int bt_field_type_enumeration_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+void finalize_enumeration_field_type_mapping(
+ struct bt_field_type_enumeration_mapping *mapping)
+{
+ BT_ASSERT(mapping);
-static
-int bt_field_type_string_compare(struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+ if (mapping->label) {
+ g_string_free(mapping->label, TRUE);
+ }
-static
-int bt_field_type_structure_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+ if (mapping->ranges) {
+ g_array_free(mapping->ranges, TRUE);
+ }
+}
static
-int bt_field_type_variant_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+void destroy_enumeration_field_type(struct bt_object *obj)
+{
+ struct bt_field_type_enumeration *ft = (void *) obj;
-static
-int bt_field_type_array_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
+ BT_ASSERT(ft);
+ BT_LIB_LOGD("Destroying enumeration field type object: %!+F", ft);
-static
-int bt_field_type_sequence_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b);
-
-static struct bt_field_type_methods bt_field_type_integer_methods = {
- .freeze = bt_field_type_generic_freeze,
- .validate = bt_field_type_integer_validate,
- .set_byte_order = bt_field_type_integer_set_byte_order,
- .copy = (bt_field_type_method_copy)
- bt_field_type_integer_copy,
- .compare = bt_field_type_integer_compare,
-};
-
-static struct bt_field_type_methods bt_field_type_floating_point_methods = {
- .freeze = bt_field_type_generic_freeze,
- .validate = NULL,
- .set_byte_order = bt_field_type_floating_point_set_byte_order,
- .copy = (bt_field_type_method_copy)
- bt_field_type_floating_point_copy,
- .compare = bt_field_type_floating_point_compare,
-};
-
-static struct bt_field_type_methods bt_field_type_enumeration_methods = {
- .freeze = bt_field_type_enumeration_freeze_recursive,
- .validate = bt_field_type_enumeration_validate_recursive,
- .set_byte_order = bt_field_type_enumeration_set_byte_order_recursive,
- .copy = (bt_field_type_method_copy)
- bt_field_type_enumeration_copy_recursive,
- .compare = bt_field_type_enumeration_compare_recursive,
-};
-
-static struct bt_field_type_methods bt_field_type_string_methods = {
- .freeze = bt_field_type_generic_freeze,
- .validate = NULL,
- .set_byte_order = NULL,
- .copy = (bt_field_type_method_copy)
- bt_field_type_string_copy,
- .compare = bt_field_type_string_compare,
-};
-
-static struct bt_field_type_methods bt_field_type_array_methods = {
- .freeze = bt_field_type_array_freeze_recursive,
- .validate = bt_field_type_array_validate_recursive,
- .set_byte_order = bt_field_type_array_set_byte_order_recursive,
- .copy = (bt_field_type_method_copy)
- bt_field_type_array_copy_recursive,
- .compare = bt_field_type_array_compare_recursive,
-};
-
-static struct bt_field_type_methods bt_field_type_sequence_methods = {
- .freeze = bt_field_type_sequence_freeze_recursive,
- .validate = bt_field_type_sequence_validate_recursive,
- .set_byte_order = bt_field_type_sequence_set_byte_order_recursive,
- .copy = (bt_field_type_method_copy)
- bt_field_type_sequence_copy_recursive,
- .compare = bt_field_type_sequence_compare_recursive,
-};
-
-static struct bt_field_type_methods bt_field_type_structure_methods = {
- .freeze = bt_field_type_structure_freeze_recursive,
- .validate = bt_field_type_structure_validate_recursive,
- .set_byte_order = bt_field_type_structure_set_byte_order_recursive,
- .copy = (bt_field_type_method_copy)
- bt_field_type_structure_copy_recursive,
- .compare = bt_field_type_structure_compare_recursive,
-};
-
-static struct bt_field_type_methods bt_field_type_variant_methods = {
- .freeze = bt_field_type_variant_freeze_recursive,
- .validate = bt_field_type_variant_validate_recursive,
- .set_byte_order = bt_field_type_variant_set_byte_order_recursive,
- .copy = (bt_field_type_method_copy)
- bt_field_type_variant_copy_recursive,
- .compare = bt_field_type_variant_compare_recursive,
-};
+ if (ft->mappings) {
+ uint64_t i;
-static
-void destroy_enumeration_mapping(struct enumeration_mapping *mapping)
-{
- g_free(mapping);
+ for (i = 0; i < ft->mappings->len; i++) {
+ finalize_enumeration_field_type_mapping(
+ BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, i));
+ }
+
+ g_array_free(ft->mappings, TRUE);
+ }
+
+ if (ft->label_buf) {
+ g_ptr_array_free(ft->label_buf, TRUE);
+ }
+
+ g_free(ft);
}
static
-void bt_field_type_initialize(struct bt_field_type *ft,
- bool init_bo, bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+struct bt_field_type *create_enumeration_field_type(enum bt_field_type_id id)
{
- BT_ASSERT(ft && (ft->id > BT_FIELD_TYPE_ID_UNKNOWN) &&
- (ft->id < BT_FIELD_TYPE_ID_NR));
+ struct bt_field_type_enumeration *enum_ft = NULL;
- bt_object_init_shared(&ft->base, release_func);
- ft->methods = methods;
+ BT_LOGD("Creating default enumeration field type object: id=%s",
+ bt_common_field_type_id_string(id));
+ enum_ft = g_new0(struct bt_field_type_enumeration, 1);
+ if (!enum_ft) {
+ BT_LOGE_STR("Failed to allocate one enumeration field type.");
+ goto error;
+ }
- if (init_bo) {
- int ret;
- const enum bt_byte_order bo = BT_BYTE_ORDER_NATIVE;
+ init_integer_field_type((void *) enum_ft, id,
+ destroy_enumeration_field_type);
+ enum_ft->mappings = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_enumeration_mapping));
+ if (!enum_ft->mappings) {
+ BT_LOGE_STR("Failed to allocate a GArray.");
+ goto error;
+ }
- BT_LOGD("Setting initial field type's byte order: bo=%s",
- bt_common_byte_order_string(bo));
- ret = bt_field_type_set_byte_order(ft, bo);
- BT_ASSERT(ret == 0);
+ enum_ft->label_buf = g_ptr_array_new();
+ if (!enum_ft->label_buf) {
+ BT_LOGE_STR("Failed to allocate a GArray.");
+ goto error;
}
- ft->alignment = 1;
+ BT_LIB_LOGD("Created enumeration field type object: %!+F", enum_ft);
+ goto end;
+
+error:
+ BT_PUT(enum_ft);
+
+end:
+ return (void *) enum_ft;
}
-static
-void bt_field_type_integer_initialize(
- struct bt_field_type *ft,
- unsigned int size, bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+struct bt_field_type *bt_field_type_unsigned_enumeration_create(void)
{
- struct bt_field_type_integer *int_ft = (void *) ft;
-
- BT_ASSERT(size > 0);
- BT_LOGD("Initializing integer field type object: size=%u",
- size);
- ft->id = BT_FIELD_TYPE_ID_INTEGER;
- int_ft->size = size;
- int_ft->base = BT_INTEGER_BASE_DECIMAL;
- int_ft->encoding = BT_STRING_ENCODING_NONE;
- bt_field_type_initialize(ft, true, release_func, methods);
- BT_LOGD("Initialized integer field type object: addr=%p, size=%u",
- ft, size);
+ return create_enumeration_field_type(
+ BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION);
}
-static
-void bt_field_type_floating_point_initialize(
- struct bt_field_type *ft,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+struct bt_field_type *bt_field_type_signed_enumeration_create(void)
{
- struct bt_field_type_floating_point *flt_ft = (void *) ft;
-
- BT_LOGD_STR("Initializing floating point number field type object.");
- ft->id = BT_FIELD_TYPE_ID_FLOAT;
- flt_ft->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
- flt_ft->mant_dig = FLT_MANT_DIG;
- bt_field_type_initialize(ft, true, release_func, methods);
- BT_LOGD("Initialized floating point number field type object: addr=%p, "
- "exp-size=%u, mant-size=%u", ft, flt_ft->exp_dig,
- flt_ft->mant_dig);
+ return create_enumeration_field_type(
+ BT_FIELD_TYPE_ID_SIGNED_ENUMERATION);
}
-static
-void bt_field_type_enumeration_initialize(
- struct bt_field_type *ft,
- struct bt_field_type *container_ft,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+uint64_t bt_field_type_enumeration_get_mapping_count(struct bt_field_type *ft)
{
struct bt_field_type_enumeration *enum_ft = (void *) ft;
- BT_ASSERT(container_ft);
- BT_LOGD("Initializing enumeration field type object: int-ft-addr=%p",
- container_ft);
- ft->id = BT_FIELD_TYPE_ID_ENUM;
- enum_ft->container_ft = bt_get(container_ft);
- enum_ft->entries = g_ptr_array_new_with_free_func(
- (GDestroyNotify) destroy_enumeration_mapping);
- bt_field_type_initialize(ft, false, release_func, methods);
- BT_LOGD("Initialized enumeration field type object: addr=%p, "
- "int-ft-addr=%p, int-ft-size=%u", ft, container_ft,
- bt_field_type_integer_get_size(container_ft));
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_ENUM(ft, "Field type");
+ return (uint64_t) enum_ft->mappings->len;
}
-static
-void bt_field_type_string_initialize(
- struct bt_field_type *ft,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+void bt_field_type_unsigned_enumeration_borrow_mapping_by_index(
+ struct bt_field_type *ft, uint64_t index,
+ const char **name,
+ struct bt_field_type_unsigned_enumeration_mapping_ranges **ranges)
{
- struct bt_field_type_string *string_ft = (void *) ft;
-
- BT_LOGD_STR("Initializing string field type object.");
- ft->id = BT_FIELD_TYPE_ID_STRING;
- bt_field_type_initialize(ft, true, release_func, methods);
- string_ft->encoding = BT_STRING_ENCODING_UTF8;
- ft->alignment = CHAR_BIT;
- BT_LOGD("Initialized string field type object: addr=%p", ft);
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ struct bt_field_type_enumeration_mapping *mapping;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_NON_NULL(name, "Name (output)");
+ BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)");
+ BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len);
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION,
+ "Field type");
+ mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index);
+ *name = mapping->label->str;
+ *ranges = (void *) mapping;
}
-static
-void bt_field_type_structure_initialize(
- struct bt_field_type *ft,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+void bt_field_type_signed_enumeration_borrow_mapping_by_index(
+ struct bt_field_type *ft, uint64_t index,
+ const char **name,
+ struct bt_field_type_signed_enumeration_mapping_ranges **ranges)
{
- struct bt_field_type_structure *struct_ft = (void *) ft;
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ struct bt_field_type_enumeration_mapping *mapping;
- BT_LOGD_STR("Initializing structure field type object.");
- ft->id = BT_FIELD_TYPE_ID_STRUCT;
- struct_ft->fields = g_array_new(FALSE, TRUE,
- sizeof(struct bt_field_type_structure_field));
- struct_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
- bt_field_type_initialize(ft, true, release_func, methods);
- BT_LOGD("Initialized structure field type object: addr=%p", ft);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_NON_NULL(name, "Name (output)");
+ BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)");
+ BT_ASSERT_PRE_VALID_INDEX(index, enum_ft->mappings->len);
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION,
+ "Field type");
+ mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(ft, index);
+ *name = mapping->label->str;
+ *ranges = (void *) mapping;
}
-static
-void bt_field_type_array_initialize(
- struct bt_field_type *ft,
- struct bt_field_type *element_ft,
- unsigned int length, bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+static inline
+uint64_t get_enumeration_field_type_mapping_range_count(
+ struct bt_field_type_enumeration_mapping *mapping)
{
- struct bt_field_type_array *array_ft = (void *) ft;
-
- BT_ASSERT(element_ft);
- BT_LOGD("Initializing array field type object: element-ft-addr=%p, "
- "length=%u", element_ft, length);
- ft->id = BT_FIELD_TYPE_ID_ARRAY;
- array_ft->element_ft = bt_get(element_ft);
- array_ft->length = length;
- bt_field_type_initialize(ft, false, release_func, methods);
- BT_LOGD("Initialized array field type object: addr=%p, "
- "element-ft-addr=%p, length=%u", ft, element_ft, length);
+ BT_ASSERT_PRE_NON_NULL(mapping, "Ranges");
+ return (uint64_t) mapping->ranges->len;
}
-static
-void bt_field_type_sequence_initialize(
- struct bt_field_type *ft,
- struct bt_field_type *element_ft,
- const char *length_field_name,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+uint64_t bt_field_type_unsigned_enumeration_mapping_ranges_get_range_count(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges)
{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- BT_ASSERT(element_ft);
- BT_ASSERT(length_field_name);
- BT_ASSERT(bt_identifier_is_valid(length_field_name));
- BT_LOGD("Initializing sequence field type object: element-ft-addr=%p, "
- "length-field-name=\"%s\"", element_ft, length_field_name);
- ft->id = BT_FIELD_TYPE_ID_SEQUENCE;
- seq_ft->element_ft = bt_get(element_ft);
- seq_ft->length_field_name = g_string_new(length_field_name);
- bt_field_type_initialize(ft, false, release_func, methods);
- BT_LOGD("Initialized sequence field type object: addr=%p, "
- "element-ft-addr=%p, length-field-name=\"%s\"",
- ft, element_ft, length_field_name);
+ return get_enumeration_field_type_mapping_range_count((void *) ranges);
}
-static
-void bt_field_type_variant_initialize(
- struct bt_field_type *ft,
- struct bt_field_type *tag_ft,
- const char *tag_name,
- bt_object_release_func release_func,
- struct bt_field_type_methods *methods)
+uint64_t bt_field_type_signed_enumeration_mapping_ranges_get_range_count(
+ struct bt_field_type_signed_enumeration_mapping_ranges *ranges)
{
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- BT_ASSERT(!tag_name || bt_identifier_is_valid(tag_name));
- BT_LOGD("Initializing variant field type object: "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- tag_ft, tag_name);
- ft->id = BT_FIELD_TYPE_ID_VARIANT;
- var_ft->tag_name = g_string_new(tag_name);
- var_ft->choice_name_to_index = g_hash_table_new(NULL, NULL);
- var_ft->choices = g_array_new(FALSE, TRUE,
- sizeof(struct bt_field_type_variant_choice));
-
- if (tag_ft) {
- var_ft->tag_ft = bt_get(tag_ft);
- }
-
- bt_field_type_initialize(ft, true, release_func, methods);
- /* A variant's alignment is undefined */
- ft->alignment = 0;
- BT_LOGD("Initialized variant field type object: addr=%p, "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- ft, tag_ft, tag_name);
+ return get_enumeration_field_type_mapping_range_count((void *) ranges);
}
-static
-void bt_field_type_integer_destroy(struct bt_object *obj)
+static inline
+void get_enumeration_field_type_mapping_range_at_index(
+ struct bt_field_type_enumeration_mapping *mapping,
+ uint64_t index, uint64_t *lower, uint64_t *upper)
{
- struct bt_field_type_integer *ft = (void *) obj;
-
- if (!ft) {
- return;
- }
+ struct bt_field_type_enumeration_mapping_range *range;
- BT_LOGD("Destroying integer field type object: addr=%p", ft);
- BT_LOGD_STR("Putting mapped clock class.");
- bt_put(ft->mapped_clock_class);
- g_free(ft);
+ BT_ASSERT_PRE_NON_NULL(mapping, "Ranges");
+ BT_ASSERT_PRE_NON_NULL(lower, "Range's lower (output)");
+ BT_ASSERT_PRE_NON_NULL(upper, "Range's upper (output)");
+ BT_ASSERT_PRE_VALID_INDEX(index, mapping->ranges->len);
+ range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping, index);
+ *lower = range->lower.u;
+ *upper = range->upper.u;
}
-static
-void bt_field_type_floating_point_destroy(struct bt_object *obj)
+void bt_field_type_unsigned_enumeration_mapping_ranges_get_range_by_index(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges,
+ uint64_t index, uint64_t *lower, uint64_t *upper)
{
- struct bt_field_type_floating_point *ft = (void *) obj;
-
- if (!ft) {
- return;
- }
-
- BT_LOGD("Destroying floating point number field type object: addr=%p", ft);
- g_free(ft);
+ get_enumeration_field_type_mapping_range_at_index((void *) ranges,
+ index, lower, upper);
}
-static
-void bt_field_type_enumeration_destroy_recursive(struct bt_object *obj)
+void bt_field_type_signed_enumeration_mapping_ranges_get_range_by_index(
+ struct bt_field_type_unsigned_enumeration_mapping_ranges *ranges,
+ uint64_t index, int64_t *lower, int64_t *upper)
{
- struct bt_field_type_enumeration *ft = (void *) obj;
+ get_enumeration_field_type_mapping_range_at_index((void *) ranges,
+ index, (uint64_t *) lower, (uint64_t *) upper);
+}
- if (!ft) {
- return;
- }
- BT_LOGD("Destroying enumeration field type object: addr=%p", ft);
- g_ptr_array_free(ft->entries, TRUE);
- BT_LOGD_STR("Putting container field type.");
- bt_put(ft->container_ft);
- g_free(ft);
-}
-static
-void bt_field_type_string_destroy(struct bt_object *obj)
+int bt_field_type_unsigned_enumeration_get_mapping_labels_by_value(
+ struct bt_field_type *ft, uint64_t value,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count)
{
- struct bt_field_type_string *ft = (void *) obj;
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ uint64_t i;
- if (!ft) {
- return;
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
+ BT_ASSERT_PRE_NON_NULL(count, "Count (output)");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION,
+ "Field type");
+ g_ptr_array_set_size(enum_ft->label_buf, 0);
+
+ for (i = 0; i < enum_ft->mappings->len; i++) {
+ uint64_t j;
+ struct bt_field_type_enumeration_mapping *mapping =
+ BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i);
+
+ for (j = 0; j < mapping->ranges->len; j++) {
+ struct bt_field_type_enumeration_mapping_range *range =
+ BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(
+ mapping, j);
+
+ if (value >= range->lower.u &&
+ value <= range->upper.u) {
+ g_ptr_array_add(enum_ft->label_buf,
+ mapping->label->str);
+ break;
+ }
+ }
}
- BT_LOGD("Destroying string field type object: addr=%p", ft);
- g_free(ft);
+ *label_array = (void *) enum_ft->label_buf->pdata;
+ *count = (uint64_t) enum_ft->label_buf->len;
+ return 0;
}
-static
-void bt_field_type_structure_field_finalize(
- struct bt_field_type_structure_field *field)
+int bt_field_type_signed_enumeration_get_mapping_labels_by_value(
+ struct bt_field_type *ft, int64_t value,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count)
{
- if (!field) {
- return;
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ uint64_t i;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
+ BT_ASSERT_PRE_NON_NULL(count, "Count (output)");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION,
+ "Field type");
+ g_ptr_array_set_size(enum_ft->label_buf, 0);
+
+ for (i = 0; i < enum_ft->mappings->len; i++) {
+ uint64_t j;
+ struct bt_field_type_enumeration_mapping *mapping =
+ BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i);
+
+ for (j = 0; j < mapping->ranges->len; j++) {
+ struct bt_field_type_enumeration_mapping_range *range =
+ BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(
+ mapping, j);
+
+ if (value >= range->lower.i &&
+ value <= range->upper.i) {
+ g_ptr_array_add(enum_ft->label_buf,
+ mapping->label->str);
+ break;
+ }
+ }
}
- BT_LOGD("Finalizing structure field type's field: "
- "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
- field, field->type, g_quark_to_string(field->name));
- BT_LOGD_STR("Putting field type.");
- bt_put(field->type);
+ *label_array = (void *) enum_ft->label_buf->pdata;
+ *count = (uint64_t) enum_ft->label_buf->len;
+ return 0;
}
-static
-void bt_field_type_structure_destroy_recursive(struct bt_object *obj)
+static inline
+int add_mapping_to_enumeration_field_type(struct bt_field_type *ft,
+ const char *label, uint64_t lower, uint64_t upper)
{
- struct bt_field_type_structure *ft = (void *) obj;
+ int ret = 0;
uint64_t i;
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ struct bt_field_type_enumeration_mapping *mapping = NULL;
+ struct bt_field_type_enumeration_mapping_range *range;
- if (!ft) {
- return;
- }
+ BT_ASSERT(ft);
+ BT_ASSERT_PRE_NON_NULL(label, "Label");
- BT_LOGD("Destroying structure field type object: addr=%p", ft);
+ /* Find existing mapping identified by this label */
+ for (i = 0; i < enum_ft->mappings->len; i++) {
+ struct bt_field_type_enumeration_mapping *mapping_candidate =
+ BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft, i);
- if (ft->fields) {
- for (i = 0; i < ft->fields->len; i++) {
- bt_field_type_structure_field_finalize(
- BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
- ft, i));
+ if (strcmp(mapping_candidate->label->str, label) == 0) {
+ mapping = mapping_candidate;
+ break;
}
-
- g_array_free(ft->fields, TRUE);
- }
-
- if (ft->field_name_to_index) {
- g_hash_table_destroy(ft->field_name_to_index);
}
- g_free(ft);
-}
-
-static
-void bt_field_type_array_destroy_recursive(struct bt_object *obj)
-{
- struct bt_field_type_array *ft = (void *) obj;
+ if (!mapping) {
+ /* Create new mapping for this label */
+ g_array_set_size(enum_ft->mappings, enum_ft->mappings->len + 1);
+ mapping = BT_FIELD_TYPE_ENUM_MAPPING_AT_INDEX(enum_ft,
+ enum_ft->mappings->len - 1);
+ mapping->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_enumeration_mapping_range));
+ if (!mapping->ranges) {
+ finalize_enumeration_field_type_mapping(mapping);
+ g_array_set_size(enum_ft->mappings,
+ enum_ft->mappings->len - 1);
+ ret = -1;
+ goto end;
+ }
- if (!ft) {
- return;
+ mapping->label = g_string_new(label);
+ if (!mapping->label) {
+ finalize_enumeration_field_type_mapping(mapping);
+ g_array_set_size(enum_ft->mappings,
+ enum_ft->mappings->len - 1);
+ ret = -1;
+ goto end;
+ }
}
- BT_LOGD("Destroying array field type object: addr=%p", ft);
- BT_LOGD_STR("Putting element field type.");
- bt_put(ft->element_ft);
- g_free(ft);
+ /* Add range */
+ BT_ASSERT(mapping);
+ g_array_set_size(mapping->ranges, mapping->ranges->len + 1);
+ range = BT_FIELD_TYPE_ENUM_MAPPING_RANGE_AT_INDEX(mapping,
+ mapping->ranges->len - 1);
+ range->lower.u = lower;
+ range->upper.u = upper;
+ BT_LIB_LOGV("Added mapping to enumeration field type: "
+ "%![ft-]+F, label=\"%s\", lower-unsigned=%" PRIu64 ", "
+ "upper-unsigned=%" PRIu64, ft, label, lower, upper);
+
+end:
+ return ret;
}
-static
-void bt_field_type_sequence_destroy_recursive(struct bt_object *obj)
+int bt_field_type_unsigned_enumeration_map_range(
+ struct bt_field_type *ft, const char *label,
+ uint64_t range_lower, uint64_t range_upper)
{
- struct bt_field_type_sequence *ft = (void *) obj;
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
- if (!ft) {
- return;
- }
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION,
+ "Field type");
+ BT_ASSERT_PRE(range_lower <= range_upper,
+ "Range's upper bound is less than lower bound: "
+ "upper=%" PRIu64 ", lower=%" PRIu64,
+ range_lower, range_upper);
+ BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range,
+ range_lower),
+ "Range's lower bound is outside the enumeration field type's value range: "
+ "%![ft-]+F, lower=%" PRIu64, ft, range_lower);
+ BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_ft->common.range,
+ range_upper),
+ "Range's upper bound is outside the enumeration field type's value range: "
+ "%![ft-]+F, upper=%" PRIu64, ft, range_upper);
+ return add_mapping_to_enumeration_field_type(ft, label, range_lower,
+ range_upper);
+}
+
+int bt_field_type_signed_enumeration_map_range(
+ struct bt_field_type *ft, const char *label,
+ int64_t range_lower, int64_t range_upper)
+{
+ struct bt_field_type_enumeration *enum_ft = (void *) ft;
- BT_LOGD("Destroying sequence field type object: addr=%p", ft);
- BT_LOGD_STR("Putting element field type.");
- bt_put(ft->element_ft);
- g_string_free(ft->length_field_name, TRUE);
- BT_LOGD_STR("Putting length field path.");
- bt_put(ft->length_field_path);
- g_free(ft);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SIGNED_ENUMERATION,
+ "Field type");
+ BT_ASSERT_PRE(range_lower <= range_upper,
+ "Range's upper bound is less than lower bound: "
+ "upper=%" PRId64 ", lower=%" PRId64,
+ range_lower, range_upper);
+ BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range,
+ range_lower),
+ "Range's lower bound is outside the enumeration field type's value range: "
+ "%![ft-]+F, lower=%" PRId64, ft, range_lower);
+ BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_ft->common.range,
+ range_upper),
+ "Range's upper bound is outside the enumeration field type's value range: "
+ "%![ft-]+F, upper=%" PRId64, ft, range_upper);
+ return add_mapping_to_enumeration_field_type(ft, label, range_lower,
+ range_upper);
}
static
-void bt_field_type_variant_choice_finalize(
- struct bt_field_type_variant_choice *choice)
+void destroy_real_field_type(struct bt_object *obj)
{
- if (!choice) {
- return;
- }
-
- BT_LOGD("Finalizing variant field type's choice: "
- "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
- choice, choice->type, g_quark_to_string(choice->name));
- BT_LOGD_STR("Putting field type.");
- bt_put(choice->type);
-
- if (choice->ranges) {
- g_array_free(choice->ranges, TRUE);
- }
+ BT_ASSERT(obj);
+ BT_LIB_LOGD("Destroying real field type object: %!+F", obj);
+ g_free(obj);
}
-static
-void bt_field_type_variant_destroy_recursive(struct bt_object *obj)
+struct bt_field_type *bt_field_type_real_create(void)
{
- struct bt_field_type_variant *ft = (void *) obj;
- uint64_t i;
-
- if (!ft) {
- return;
- }
+ struct bt_field_type_real *real_ft = NULL;
- BT_LOGD("Destroying variant field type object: addr=%p", ft);
-
- if (ft->choices) {
- for (i = 0; i < ft->choices->len; i++) {
- bt_field_type_variant_choice_finalize(
- BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
- ft, i));
- }
-
- g_array_free(ft->choices, TRUE);
+ BT_LOGD_STR("Creating default real field type object.");
+ real_ft = g_new0(struct bt_field_type_real, 1);
+ if (!real_ft) {
+ BT_LOGE_STR("Failed to allocate one real field type.");
+ goto error;
}
- if (ft->choice_name_to_index) {
- g_hash_table_destroy(ft->choice_name_to_index);
- }
+ init_field_type((void *) real_ft, BT_FIELD_TYPE_ID_REAL,
+ destroy_real_field_type);
+ BT_LIB_LOGD("Created real field type object: %!+F", real_ft);
+ goto end;
- if (ft->tag_name) {
- g_string_free(ft->tag_name, TRUE);
- }
+error:
+ BT_PUT(real_ft);
- BT_LOGD_STR("Putting tag field type.");
- bt_put(ft->tag_ft);
- BT_LOGD_STR("Putting tag field path.");
- bt_put(ft->tag_field_path);
- g_free(ft);
+end:
+ return (void *) real_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
-gint compare_enumeration_mappings_signed(struct enumeration_mapping **a,
- struct enumeration_mapping **b)
+bt_bool bt_field_type_real_is_single_precision(struct bt_field_type *ft)
{
- return ((*a)->range_start._signed < (*b)->range_start._signed) ? -1 : 1;
+ struct bt_field_type_real *real_ft = (void *) ft;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type");
+ return real_ft->is_single_precision;
}
-static
-gint compare_enumeration_mappings_unsigned(struct enumeration_mapping **a,
- struct enumeration_mapping **b)
+int bt_field_type_real_set_is_single_precision(struct bt_field_type *ft,
+ bt_bool is_single_precision)
{
- return ((*a)->range_start._unsigned < (*b)->range_start._unsigned) ? -1 : 1;
+ struct bt_field_type_real *real_ft = (void *) ft;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_REAL, "Field type");
+ BT_ASSERT_PRE_FT_HOT(ft, "Field type");
+ real_ft->is_single_precision = (bool) is_single_precision;
+ BT_LIB_LOGV("Set real field type's \"is single precision\" property: "
+ "%!+F", ft);
+ return 0;
}
static
-int add_structure_variant_member(GArray *members,
- GHashTable *field_name_to_index,
- struct bt_field_type *field_type, const char *field_name,
- bool is_variant)
+int init_named_field_types_container(
+ struct bt_field_type_named_field_types_container *ft,
+ enum bt_field_type_id id, bt_object_release_func release_func)
{
int ret = 0;
- GQuark name_quark = g_quark_from_string(field_name);
- struct bt_field_type **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);
+
+ init_field_type((void *) ft, id, release_func);
+ ft->named_fts = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_named_field_type));
+ if (!ft->named_fts) {
+ BT_LOGE_STR("Failed to allocate a GArray.");
ret = -1;
goto end;
}
- g_array_set_size(members, members->len + 1);
-
- if (is_variant) {
- struct bt_field_type_variant_choice *choice =
- &g_array_index(members,
- struct bt_field_type_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_field_type_variant_choice_range));
- BT_ASSERT(choice->ranges);
- } else {
- struct bt_field_type_structure_field *field =
- &g_array_index(members,
- struct bt_field_type_structure_field,
- members->len - 1);
-
- member_ft = &field->type;
- member_name = &field->name;
+ ft->name_to_index = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!ft->name_to_index) {
+ BT_LOGE_STR("Failed to allocate a GHashTable.");
+ ret = -1;
+ goto end;
}
- *member_name = name_quark;
- *member_ft = bt_get(field_type);
- g_hash_table_insert(field_name_to_index,
- GUINT_TO_POINTER(name_quark),
- GUINT_TO_POINTER(members->len - 1));
- BT_LOGV("Added structure/variant field type member: member-ft-addr=%p, "
- "member-name=\"%s\"", field_type, field_name);
-
end:
return ret;
}
static
-int bt_field_type_integer_validate(struct bt_field_type *ft)
+void finalize_named_field_type(struct bt_named_field_type *named_ft)
{
- int ret = 0;
- struct bt_field_type_integer *int_ft = (void *) ft;
+ BT_ASSERT(named_ft);
+ BT_LIB_LOGD("Finalizing named field type: "
+ "addr=%p, name=\"%s\", %![ft-]+F",
+ named_ft, named_ft->name ? named_ft->name->str : NULL,
+ named_ft->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_clock_class_get_name(int_ft->mapped_clock_class));
- ret = -1;
- goto end;
+ if (named_ft->name) {
+ g_string_free(named_ft->name, TRUE);
}
-end:
- return ret;
+ BT_LOGD_STR("Putting named field type's field type.");
+ bt_put(named_ft->ft);
}
static
-struct enumeration_mapping *bt_field_type_enumeration_get_mapping_by_index(
- struct bt_field_type *ft, uint64_t index)
+void finalize_named_field_types_container(
+ struct bt_field_type_named_field_types_container *ft)
{
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
- struct enumeration_mapping *mapping = NULL;
+ uint64_t i;
- 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_ASSERT(ft);
-/*
- * Note: This algorithm is O(n^2) vs number of enumeration mappings.
- * Only used when freezing an enumeration.
- */
-static
-void bt_field_type_enumeration_set_range_overlap(
- struct bt_field_type_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_field_type_integer_is_signed((void *) ft->container_ft);
-
- for (i = 0; i < len; i++) {
- for (j = i + 1; j < len; j++) {
- struct enumeration_mapping *mapping[2];
-
- mapping[0] = bt_field_type_enumeration_get_mapping_by_index(
- (void *) ft, i);
- mapping[1] = bt_field_type_enumeration_get_mapping_by_index(
- (void *) 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;
- }
- }
+ if (ft->named_fts) {
+ for (i = 0; i < ft->named_fts->len; i++) {
+ finalize_named_field_type(
+ &g_array_index(ft->named_fts,
+ struct bt_named_field_type, i));
}
+
+ g_array_free(ft->named_fts, TRUE);
}
-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.");
+ if (ft->name_to_index) {
+ g_hash_table_destroy(ft->name_to_index);
}
}
static
-int bt_field_type_enumeration_validate_recursive(
- struct bt_field_type *ft)
+void destroy_structure_field_type(struct bt_object *obj)
{
- int ret = 0;
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
+ BT_ASSERT(obj);
+ BT_LIB_LOGD("Destroying string field type object: %!+F", obj);
+ finalize_named_field_types_container((void *) obj);
+ g_free(obj);
+}
- ret = bt_field_type_integer_validate((void *) 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;
+struct bt_field_type *bt_field_type_structure_create(void)
+{
+ int ret;
+ struct bt_field_type_structure *struct_ft = NULL;
+
+ BT_LOGD_STR("Creating default structure field type object.");
+ struct_ft = g_new0(struct bt_field_type_structure, 1);
+ if (!struct_ft) {
+ BT_LOGE_STR("Failed to allocate one structure field type.");
+ goto error;
}
- /* 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;
+ ret = init_named_field_types_container((void *) struct_ft,
+ BT_FIELD_TYPE_ID_STRUCTURE, destroy_structure_field_type);
+ if (ret) {
+ goto error;
}
+ BT_LIB_LOGD("Created structure field type object: %!+F", struct_ft);
+ goto end;
+
+error:
+ BT_PUT(struct_ft);
+
end:
- return ret;
+ return (void *) struct_ft;
}
static
-int bt_field_type_sequence_validate_recursive(
- struct bt_field_type *ft)
+int append_named_field_type_to_container_field_type(
+ struct bt_field_type_named_field_types_container *container_ft,
+ const char *name, struct bt_field_type *ft)
{
int ret = 0;
- struct bt_field_type_sequence *seq_ft = (void *) ft;
+ struct bt_named_field_type *named_ft;
+ GString *name_str;
- /* 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);
+ BT_ASSERT(container_ft);
+ BT_ASSERT_PRE_FT_HOT(container_ft, "Field type");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE(!bt_g_hash_table_contains(container_ft->name_to_index,
+ name),
+ "Duplicate member/option name in structure/variant field type: "
+ "%![container-ft-]+F, name=\"%s\"", container_ft, name);
+ name_str = g_string_new(name);
+ if (!name_str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
ret = -1;
goto end;
}
- ret = bt_field_type_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);
- }
+ g_array_set_size(container_ft->named_fts,
+ container_ft->named_fts->len + 1);
+ named_ft = &g_array_index(container_ft->named_fts,
+ struct bt_named_field_type, container_ft->named_fts->len - 1);
+ named_ft->name = name_str;
+ named_ft->ft = bt_get(ft);
+ g_hash_table_insert(container_ft->name_to_index, named_ft->name->str,
+ GUINT_TO_POINTER(container_ft->named_fts->len - 1));
+ bt_field_type_freeze(ft);
end:
return ret;
}
-static
-int bt_field_type_array_validate_recursive(
- struct bt_field_type *ft)
+int bt_field_type_structure_append_member(struct bt_field_type *ft,
+ const char *name, struct bt_field_type *member_ft)
{
- int ret = 0;
- struct bt_field_type_array *array_ft = (void *) ft;
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type");
+ return append_named_field_type_to_container_field_type((void *) ft,
+ name, member_ft);
+}
- ret = bt_field_type_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);
- }
+uint64_t bt_field_type_structure_get_member_count(struct bt_field_type *ft)
+{
+ struct bt_field_type_structure *struct_ft = (void *) ft;
- return ret;
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type");
+ return (uint64_t) struct_ft->common.named_fts->len;
}
static
-int bt_field_type_structure_validate_recursive(
- struct bt_field_type *ft)
+void borrow_named_field_type_from_container_field_type_at_index(
+ struct bt_field_type_named_field_types_container *ft,
+ uint64_t index, const char **name,
+ struct bt_field_type **out_ft)
{
- int ret = 0;
- struct bt_field_type *child_ft = NULL;
- int64_t field_count =
- bt_field_type_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_field_type_structure_borrow_field_by_index(ft,
- &field_name, &child_ft, i);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_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;
- }
- }
+ struct bt_named_field_type *named_ft;
-end:
- return ret;
+ BT_ASSERT(ft);
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_NON_NULL(out_ft, "Field type (output)");
+ BT_ASSERT_PRE_VALID_INDEX(index, ft->named_fts->len);
+ named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, index);
+ *name = named_ft->name->str;
+ *out_ft = named_ft->ft;
}
-static
-bt_bool bt_field_type_enumeration_has_overlapping_ranges(
- struct bt_field_type_enumeration *enum_ft)
+void bt_field_type_structure_borrow_member_by_index(
+ struct bt_field_type *ft, uint64_t index,
+ const char **name, struct bt_field_type **out_ft)
{
- if (!enum_ft->common.frozen) {
- bt_field_type_enumeration_set_range_overlap(enum_ft);
- }
-
- return enum_ft->has_overlapping_ranges;
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type");
+ borrow_named_field_type_from_container_field_type_at_index((void *) ft,
+ index, name, out_ft);
}
static
-int bt_field_type_variant_validate_recursive(
- struct bt_field_type *ft)
+struct bt_field_type *borrow_field_type_from_container_field_type_by_name(
+ struct bt_field_type_named_field_types_container *ft,
+ const char *name)
{
- int ret = 0;
- int64_t field_count;
- struct bt_field_type *child_ft = NULL;
- struct bt_field_type_variant *var_ft = (void *) 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_field_type_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;
- }
+ struct bt_field_type *ret_ft = NULL;
+ struct bt_named_field_type *named_ft;
+ gpointer orig_key;
+ gpointer value;
- /*
- * 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_field_type_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;
+ BT_ASSERT(ft);
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ if (!g_hash_table_lookup_extended(ft->name_to_index, name, &orig_key,
+ &value)) {
goto end;
}
- for (i = 0; i < field_count; ++i) {
- const char *field_name;
-
- ret = bt_field_type_variant_borrow_field_by_index(ft,
- &field_name, &child_ft, i);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_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;
- }
- }
+ named_ft = BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft,
+ GPOINTER_TO_UINT(value));
+ ret_ft = named_ft->ft;
end:
- return ret;
+ return ret_ft;
}
-/*
- * 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_field_type_validate(struct bt_field_type *ft)
+struct bt_field_type *bt_field_type_structure_borrow_member_field_type_by_name(
+ struct bt_field_type *ft, const char *name)
{
- int ret = 0;
-
- BT_ASSERT(ft);
-
- if (ft->valid) {
- /* Already marked as valid */
- goto end;
- }
-
- if (ft->methods->validate) {
- ret = ft->methods->validate(ft);
- }
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCTURE, "Field type");
+ return borrow_field_type_from_container_field_type_by_name((void *) ft,
+ name);
+}
- if (ret == 0 && ft->frozen) {
- /* Field type is valid */
- BT_LOGV("Marking field type as valid: addr=%p", ft);
- ft->valid = 1;
- }
+static
+void destroy_variant_field_type(struct bt_object *obj)
+{
+ struct bt_field_type_variant *ft = (void *) obj;
-end:
- return ret;
+ BT_ASSERT(ft);
+ BT_LIB_LOGD("Destroying variant field type object: %!+F", ft);
+ finalize_named_field_types_container((void *) ft);
+ BT_LOGD_STR("Putting selector field path.");
+ bt_put(ft->selector_field_path);
+ g_free(ft);
}
-struct bt_field_type *bt_field_type_integer_create(unsigned int size)
+struct bt_field_type *bt_field_type_variant_create(void)
{
- struct bt_field_type_integer *integer = NULL;
-
- BT_LOGD("Creating integer field type object: size=%u", size);
+ int ret;
+ struct bt_field_type_variant *var_ft = NULL;
- if (size == 0 || size > 64) {
- BT_LOGW("Invalid parameter: size must be between 1 and 64: "
- "size=%u", size);
+ BT_LOGD_STR("Creating default variant field type object.");
+ var_ft = g_new0(struct bt_field_type_variant, 1);
+ if (!var_ft) {
+ BT_LOGE_STR("Failed to allocate one variant field type.");
goto error;
}
- integer = g_new0(struct bt_field_type_integer, 1);
- if (!integer) {
- BT_LOGE_STR("Failed to allocate one integer field type.");
+ ret = init_named_field_types_container((void *) var_ft,
+ BT_FIELD_TYPE_ID_VARIANT, destroy_variant_field_type);
+ if (ret) {
goto error;
}
- bt_field_type_integer_initialize((void *) integer,
- size, bt_field_type_integer_destroy,
- &bt_field_type_integer_methods);
- BT_LOGD("Created integer field type object: addr=%p, size=%u",
- integer, size);
+ BT_LIB_LOGD("Created variant field type object: %!+F", var_ft);
goto end;
error:
- BT_PUT(integer);
+ BT_PUT(var_ft);
end:
- return (void *) integer;
+ return (void *) var_ft;
}
-
-int bt_field_type_integer_get_size(struct bt_field_type *ft)
+int bt_field_type_variant_set_selector_field_type(
+ struct bt_field_type *ft, struct bt_field_type *selector_ft)
{
- struct bt_field_type_integer *int_ft = (void *) ft;
+ struct bt_field_type_variant *var_ft = (void *) ft;
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
- "Field type");
- return (int) int_ft->size;
+ BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
+ BT_ASSERT_PRE_NON_NULL(selector_ft, "Selector field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+ BT_ASSERT_PRE_FT_IS_ENUM(selector_ft, "Selector field type");
+ BT_ASSERT_PRE_FT_HOT(ft, "Variant field type");
+ var_ft->selector_ft = selector_ft;
+ bt_field_type_freeze(selector_ft);
+ return 0;
}
-bt_bool bt_field_type_integer_is_signed(struct bt_field_type *ft)
+int bt_field_type_variant_append_option(struct bt_field_type *ft,
+ const char *name, struct bt_field_type *option_ft)
{
- struct bt_field_type_integer *int_ft = (void *) ft;
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+ return append_named_field_type_to_container_field_type((void *) ft,
+ name, option_ft);
+}
+struct bt_field_type *bt_field_type_variant_borrow_option_field_type_by_name(
+ struct bt_field_type *ft, const char *name)
+{
BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
- "Field type");
- return int_ft->is_signed;
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+ return borrow_field_type_from_container_field_type_by_name((void *) ft,
+ name);
}
-int bt_field_type_integer_set_is_signed(struct bt_field_type *ft,
- bt_bool is_signed)
+uint64_t bt_field_type_variant_get_option_count(struct bt_field_type *ft)
{
- int ret = 0;
- struct bt_field_type_integer *int_ft = (void *) ft;
+ struct bt_field_type_variant *var_ft = (void *) ft;
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+ return (uint64_t) var_ft->common.named_fts->len;
+}
- if (ft->frozen) {
- BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
- ft);
- ret = -1;
- goto end;
- }
+void bt_field_type_variant_borrow_option_by_index(
+ struct bt_field_type *ft, uint64_t index,
+ const char **name, struct bt_field_type **out_ft)
+{
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+ borrow_named_field_type_from_container_field_type_at_index((void *) ft,
+ index, name, out_ft);
+}
- if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: field type is not an integer field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
+struct bt_field_path *bt_field_type_variant_borrow_selector_field_path(
+ struct bt_field_type *ft)
+{
+ struct bt_field_type_variant *var_ft = (void *) ft;
- int_ft->is_signed = !!is_signed;
- BT_LOGV("Set integer field type's signedness: addr=%p, is-signed=%d",
- ft, is_signed);
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+ "Field type");
+ return var_ft->selector_field_path;
+}
-end:
- return ret;
+static
+void init_array_field_type(struct bt_field_type_array *ft,
+ enum bt_field_type_id id, bt_object_release_func release_func,
+ struct bt_field_type *element_ft)
+{
+ BT_ASSERT(element_ft);
+ init_field_type((void *) ft, id, release_func);
+ ft->element_ft = bt_get(element_ft);
+ bt_field_type_freeze(element_ft);
}
-int bt_field_type_integer_set_size(struct bt_field_type *ft,
- unsigned int size)
+static
+void finalize_array_field_type(struct bt_field_type_array *array_ft)
{
- int ret = 0;
- struct bt_field_type_integer *int_ft = (void *) ft;
+ BT_ASSERT(array_ft);
+ BT_LOGD_STR("Putting element field type.");
+ bt_put(array_ft->element_ft);
+}
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
+static
+void destroy_static_array_field_type(struct bt_object *obj)
+{
+ BT_ASSERT(obj);
+ BT_LIB_LOGD("Destroying static array field type object: %!+F", obj);
+ finalize_array_field_type((void *) obj);
+ g_free(obj);
+}
- if (ft->frozen) {
- BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
- ft);
- ret = -1;
- goto end;
- }
+struct bt_field_type *bt_field_type_static_array_create(
+ struct bt_field_type *element_ft, uint64_t length)
+{
+ struct bt_field_type_static_array *array_ft = NULL;
- if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: field type is not an integer field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
+ BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type");
+ BT_LOGD_STR("Creating default static array field type object.");
+ array_ft = g_new0(struct bt_field_type_static_array, 1);
+ if (!array_ft) {
+ BT_LOGE_STR("Failed to allocate one static array field type.");
+ goto error;
}
- 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;
- }
+ init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_STATIC_ARRAY,
+ destroy_static_array_field_type, element_ft);
+ array_ft->length = length;
+ BT_LIB_LOGD("Created static array field type object: %!+F", array_ft);
+ goto end;
- int_ft->size = size;
- BT_LOGV("Set integer field type's size: addr=%p, size=%u",
- ft, size);
+error:
+ BT_PUT(array_ft);
end:
- return ret;
+ return (void *) array_ft;
}
-enum bt_integer_base bt_field_type_integer_get_base(
+struct bt_field_type *bt_field_type_array_borrow_element_field_type(
struct bt_field_type *ft)
{
- struct bt_field_type_integer *int_ft = (void *) ft;
+ struct bt_field_type_array *array_ft = (void *) ft;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_IS_ARRAY(ft, "Field type");
+ return array_ft->element_ft;
+}
+
+uint64_t bt_field_type_static_array_get_length(struct bt_field_type *ft)
+{
+ struct bt_field_type_static_array *array_ft = (void *) ft;
BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STATIC_ARRAY,
"Field type");
- return int_ft->base;
+ return (uint64_t) array_ft->length;
}
-int bt_field_type_integer_set_base(struct bt_field_type *ft,
- enum bt_integer_base base)
+static
+void destroy_dynamic_array_field_type(struct bt_object *obj)
{
- int ret = 0;
- struct bt_field_type_integer *int_ft = (void *) ft;
+ struct bt_field_type_dynamic_array *ft = (void *) obj;
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
+ BT_ASSERT(ft);
+ BT_LIB_LOGD("Destroying dynamic array field type object: %!+F", ft);
+ finalize_array_field_type((void *) ft);
+ BT_LOGD_STR("Putting length field path.");
+ bt_put(ft->length_field_path);
+ g_free(ft);
+}
- if (ft->frozen) {
- BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
- ft);
- ret = -1;
- goto end;
- }
+struct bt_field_type *bt_field_type_dynamic_array_create(
+ struct bt_field_type *element_ft)
+{
+ struct bt_field_type_dynamic_array *array_ft = NULL;
- if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: field type is not an integer field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
+ BT_ASSERT_PRE_NON_NULL(element_ft, "Element field type");
+ BT_LOGD_STR("Creating default dynamic array field type object.");
+ array_ft = g_new0(struct bt_field_type_dynamic_array, 1);
+ if (!array_ft) {
+ BT_LOGE_STR("Failed to allocate one dynamic array field type.");
+ goto error;
}
- switch (base) {
- case BT_INTEGER_BASE_UNSPECIFIED:
- case BT_INTEGER_BASE_BINARY:
- case BT_INTEGER_BASE_OCTAL:
- case BT_INTEGER_BASE_DECIMAL:
- case BT_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;
- }
+ init_array_field_type((void *) array_ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY,
+ destroy_dynamic_array_field_type, element_ft);
+ BT_LIB_LOGD("Created dynamic array field type object: %!+F", array_ft);
+ goto end;
- BT_LOGV("Set integer field type's base: addr=%p, base=%s",
- ft, bt_common_integer_base_string(base));
+error:
+ BT_PUT(array_ft);
end:
- return ret;
+ return (void *) array_ft;
+}
+
+int bt_field_type_dynamic_array_set_length_field_type(struct bt_field_type *ft,
+ struct bt_field_type *length_ft)
+{
+ struct bt_field_type_dynamic_array *array_ft = (void *) ft;
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Dynamic array field type");
+ BT_ASSERT_PRE_NON_NULL(length_ft, "Length field type");
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY,
+ "Field type");
+ BT_ASSERT_PRE_FT_IS_UNSIGNED_INT(length_ft, "Length field type");
+ BT_ASSERT_PRE_FT_HOT(ft, "Dynamic array field type");
+ array_ft->length_ft = length_ft;
+ bt_field_type_freeze(length_ft);
+ return 0;
}
-enum bt_string_encoding bt_field_type_integer_get_encoding(
+struct bt_field_path *bt_field_type_dynamic_array_borrow_length_field_path(
struct bt_field_type *ft)
{
- struct bt_field_type_integer *int_ft = (void *) ft;
+ struct bt_field_type_dynamic_array *seq_ft = (void *) ft;
BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+ BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_DYNAMIC_ARRAY,
"Field type");
- return int_ft->encoding;
+ return seq_ft->length_field_path;
}
-int bt_field_type_integer_set_encoding(struct bt_field_type *ft,
- enum bt_string_encoding encoding)
+static
+void destroy_string_field_type(struct bt_object *obj)
{
- int ret = 0;
- struct bt_field_type_integer *int_ft = (void *) ft;
+ BT_ASSERT(obj);
+ BT_LIB_LOGD("Destroying string field type object: %!+F", obj);
+ g_free(obj);
+}
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
+struct bt_field_type *bt_field_type_string_create(void)
+{
+ struct bt_field_type_string *string_ft = NULL;
- if (ft->frozen) {
- BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
- ft);
- ret = -1;
- goto end;
+ BT_LOGD_STR("Creating default string field type object.");
+ string_ft = g_new0(struct bt_field_type_string, 1);
+ if (!string_ft) {
+ BT_LOGE_STR("Failed to allocate one string field type.");
+ goto error;
}
- if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: field type is not an integer field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
+ init_field_type((void *) string_ft, BT_FIELD_TYPE_ID_STRING,
+ destroy_string_field_type);
+ BT_LIB_LOGD("Created string field type object: %!+F", string_ft);
+ goto end;
- if (encoding != BT_STRING_ENCODING_UTF8 &&
- encoding != BT_STRING_ENCODING_ASCII &&
- encoding != BT_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_common_string_encoding_string(encoding));
-
-end:
- return ret;
-}
-
-struct bt_clock_class *bt_field_type_integer_borrow_mapped_clock_class(
- struct bt_field_type *ft)
-{
- struct bt_field_type_integer *int_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
- "Field type");
- return int_ft->mapped_clock_class;
-}
-
-static
-int bt_field_type_integer_set_mapped_clock_class_no_check_frozen(
- struct bt_field_type *ft,
- struct bt_clock_class *clock_class)
-{
- struct bt_field_type_integer *int_ft = (void *) ft;
- int ret = 0;
-
- if (!clock_class) {
- BT_LOGW_STR("Invalid parameter: clock class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: field type is not an integer field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- goto end;
- }
-
- if (!bt_clock_class_is_valid(clock_class)) {
- BT_LOGW("Invalid parameter: clock class is invalid: ft-addr=%p"
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- ft, clock_class,
- bt_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
-
- bt_put(int_ft->mapped_clock_class);
- int_ft->mapped_clock_class = bt_get(clock_class);
- BT_LOGV("Set integer field type's mapped clock class: ft-addr=%p, "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- ft, clock_class, bt_clock_class_get_name(clock_class));
-
-end:
- return ret;
-}
-
-int bt_field_type_integer_set_mapped_clock_class(struct bt_field_type *ft,
- struct bt_clock_class *clock_class)
-{
- 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_field_type_integer_set_mapped_clock_class_no_check_frozen(
- ft, clock_class);
-
-end:
- return ret;
-}
-
-static
-void bt_field_type_enum_iter_destroy(struct bt_object *obj)
-{
- struct bt_field_type_enumeration_mapping_iterator *iter =
- container_of(obj,
- struct bt_field_type_enumeration_mapping_iterator,
- base);
-
- BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p",
- obj);
- BT_LOGD_STR("Putting parent enumeration field type.");
- bt_put(iter->enumeration_ft);
- g_free(iter);
-}
-
-static
-struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_type(
- struct bt_field_type *ft,
- enum bt_field_type_enumeration_mapping_iterator_type iterator_type)
-{
- struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM,
- "Field type");
- iter = g_new0(struct bt_field_type_enumeration_mapping_iterator, 1);
- if (!iter) {
- BT_LOGE_STR("Failed to allocate one enumeration field type mapping.");
- goto end;
- }
-
- bt_object_init_shared(&iter->base, bt_field_type_enum_iter_destroy);
- iter->enumeration_ft = bt_get(ft);
- iter->index = -1;
- iter->type = iterator_type;
-
-end:
- return iter;
-}
-
-struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_name(
- struct bt_field_type *ft, const char *name)
-{
- struct bt_field_type_enumeration_mapping_iterator *iter;
-
- iter = bt_field_type_enumeration_find_mappings_type(
- ft, ITERATOR_BY_NAME);
- if (!iter) {
- BT_LOGW("Cannot create enumeration field type mapping iterator: "
- "ft-addr=%p, mapping-name=\"%s\"", ft, name);
- goto error;
- }
-
- iter->u.name_quark = g_quark_try_string(name);
- if (!iter->u.name_quark) {
- /*
- * No results are possible, set the iterator's position at the
- * end.
- */
- iter->index = iter->enumeration_ft->entries->len;
- }
-
- return iter;
-
-error:
- bt_put(iter);
- return NULL;
-}
-
-int bt_field_type_enumeration_mapping_iterator_next(
- struct bt_field_type_enumeration_mapping_iterator *iter)
-{
- struct bt_field_type_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 enumeration_mapping *mapping =
- bt_field_type_enumeration_get_mapping_by_index(
- (void *) enum_ft, i);
-
- switch (iter->type) {
- case ITERATOR_BY_NAME:
- if (mapping->string == iter->u.name_quark) {
- iter->index = i;
- goto end;
- }
- break;
- case 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 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;
-}
-
-struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_signed_find_mappings_by_value(
- struct bt_field_type *ft, int64_t value)
-{
- struct bt_field_type_enumeration_mapping_iterator *iter;
-
- iter = bt_field_type_enumeration_find_mappings_type(
- ft, ITERATOR_BY_SIGNED_VALUE);
- if (!iter) {
- BT_LOGW("Cannot create enumeration field type mapping iterator: "
- "ft-addr=%p, value=%" PRId64, ft, value);
- goto error;
- }
-
- if (bt_field_type_integer_is_signed(
- (void *) iter->enumeration_ft->container_ft) != 1) {
- BT_LOGW("Invalid parameter: enumeration field type is unsigned: "
- "enum-ft-addr=%p, int-ft-addr=%p",
- ft, iter->enumeration_ft->container_ft);
- goto error;
- }
-
- iter->u.signed_value = value;
- return iter;
-
-error:
- bt_put(iter);
- return NULL;
-}
-
-struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_unsigned_find_mappings_by_value(
- struct bt_field_type *ft, uint64_t value)
-{
- struct bt_field_type_enumeration_mapping_iterator *iter;
-
- iter = bt_field_type_enumeration_find_mappings_type(
- ft, ITERATOR_BY_UNSIGNED_VALUE);
- if (!iter) {
- BT_LOGW("Cannot create enumeration field type mapping iterator: "
- "ft-addr=%p, value=%" PRIu64, ft, value);
- goto error;
- }
-
- if (bt_field_type_integer_is_signed(
- (void *) iter->enumeration_ft->container_ft) != 0) {
- BT_LOGW("Invalid parameter: enumeration field type is signed: "
- "enum-ft-addr=%p, int-ft-addr=%p",
- ft, iter->enumeration_ft->container_ft);
- goto error;
- }
-
- iter->u.unsigned_value = value;
- return iter;
-
-error:
- bt_put(iter);
- return NULL;
-}
-
-int bt_field_type_enumeration_mapping_iterator_signed_get(
- struct bt_field_type_enumeration_mapping_iterator *iter,
- const char **mapping_name, int64_t *range_begin,
- int64_t *range_end)
-{
- 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_field_type_enumeration_signed_get_mapping_by_index(
- (void *) iter->enumeration_ft, iter->index,
- mapping_name, range_begin, range_end);
-}
-
-int bt_field_type_enumeration_mapping_iterator_unsigned_get(
- struct bt_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_field_type_enumeration_unsigned_get_mapping_by_index(
- (void *) iter->enumeration_ft, iter->index,
- mapping_name, range_begin, range_end);
-}
-
-int bt_field_type_enumeration_signed_get_mapping_by_index(
- struct bt_field_type *ft, uint64_t index,
- const char **mapping_name, int64_t *range_begin,
- int64_t *range_end)
-{
- int ret = 0;
- struct enumeration_mapping *mapping;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft,
- BT_FIELD_TYPE_ID_ENUM, "Field type");
- mapping = bt_field_type_enumeration_get_mapping_by_index(ft,
- index);
- if (!mapping) {
- /* bt_field_type_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;
-}
-
-int bt_field_type_enumeration_unsigned_get_mapping_by_index(
- struct bt_field_type *ft, uint64_t index,
- const char **mapping_name, uint64_t *range_begin,
- uint64_t *range_end)
-{
- int ret = 0;
- struct enumeration_mapping *mapping;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
- mapping = bt_field_type_enumeration_get_mapping_by_index(
- ft, index);
- if (!mapping) {
- /* bt_field_type_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;
-}
-
-struct bt_field_type *bt_field_type_enumeration_create(
- struct bt_field_type *container_ft)
-{
- struct bt_field_type_enumeration *enumeration = NULL;
- struct bt_field_type *int_ft = (void *) container_ft;
-
- BT_LOGD("Creating enumeration field type object: int-ft-addr=%p",
- container_ft);
-
- if (!container_ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- goto error;
- }
-
- if (int_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid parameter: container field type is not an integer field type: "
- "container-ft-addr=%p, container-ft-id=%s",
- container_ft, bt_common_field_type_id_string(int_ft->id));
- goto error;
- }
-
- enumeration = g_new0(struct bt_field_type_enumeration, 1);
- if (!enumeration) {
- BT_LOGE_STR("Failed to allocate one enumeration field type.");
- goto error;
- }
-
- bt_field_type_enumeration_initialize((void *) enumeration,
- int_ft, bt_field_type_enumeration_destroy_recursive,
- &bt_field_type_enumeration_methods);
- BT_LOGD("Created enumeration field type object: addr=%p, "
- "int-ft-addr=%p, int-ft-size=%u",
- enumeration, container_ft,
- bt_field_type_integer_get_size(container_ft));
- goto end;
-
-error:
- BT_PUT(enumeration);
-
-end:
- return (void *) enumeration;
-}
-
-struct bt_field_type *bt_field_type_enumeration_borrow_container_field_type(
- struct bt_field_type *ft)
-{
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
- return (void *) enum_ft->container_ft;
-}
-
-int bt_field_type_enumeration_signed_add_mapping(
- struct bt_field_type *ft, const char *string,
- int64_t range_start, int64_t range_end)
-{
- int ret = 0;
- GQuark mapping_name;
- struct enumeration_mapping *mapping;
- struct bt_field_type_enumeration *enum_ft = (void *) 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_FIELD_TYPE_ID_ENUM) {
- BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_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 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 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;
-}
-
-int bt_field_type_enumeration_unsigned_add_mapping(
- struct bt_field_type *ft, const char *string,
- uint64_t range_start, uint64_t range_end)
-{
- int ret = 0;
- GQuark mapping_name;
- struct enumeration_mapping *mapping;
- struct bt_field_type_enumeration *enum_ft = (void *) 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_FIELD_TYPE_ID_ENUM) {
- BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_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 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 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;
-}
-
-int64_t bt_field_type_enumeration_get_mapping_count(
- struct bt_field_type *ft)
-{
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
- return (int64_t) enum_ft->entries->len;
-}
-
-struct bt_field_type *bt_field_type_floating_point_create(void)
-{
- struct bt_field_type_floating_point *floating_point =
- g_new0(struct bt_field_type_floating_point, 1);
-
- BT_LOGD_STR("Creating floating point number field type object.");
-
- if (!floating_point) {
- BT_LOGE_STR("Failed to allocate one floating point number field type.");
- goto end;
- }
-
- bt_field_type_floating_point_initialize(
- (void *) floating_point,
- bt_field_type_floating_point_destroy,
- &bt_field_type_floating_point_methods);
- BT_LOGD("Created floating point number field type object: addr=%p, "
- "exp-size=%u, mant-size=%u", floating_point,
- floating_point->exp_dig, floating_point->mant_dig);
-
-end:
- return (void *) floating_point;
-}
-
-int bt_field_type_floating_point_get_exponent_digits(
- struct bt_field_type *ft)
-{
- struct bt_field_type_floating_point *flt_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_FLOAT,
- "Field type");
- return (int) flt_ft->exp_dig;
-}
-
-int bt_field_type_floating_point_set_exponent_digits(
- struct bt_field_type *ft, unsigned int exponent_digits)
-{
- int ret = 0;
- struct bt_field_type_floating_point *flt_ft = (void *) 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_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_common_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;
-}
-
-int bt_field_type_floating_point_get_mantissa_digits(
- struct bt_field_type *ft)
-{
- struct bt_field_type_floating_point *flt_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_FLOAT,
- "Field type");
- return (int) flt_ft->mant_dig;
-}
-
-int bt_field_type_floating_point_set_mantissa_digits(
- struct bt_field_type *ft, unsigned int mantissa_digits)
-{
- int ret = 0;
- struct bt_field_type_floating_point *flt_ft = (void *) 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_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_common_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;
-}
-
-struct bt_field_type *bt_field_type_structure_create(void)
-{
- struct bt_field_type_structure *structure =
- g_new0(struct bt_field_type_structure, 1);
-
- BT_LOGD_STR("Creating structure field type object.");
-
- if (!structure) {
- BT_LOGE_STR("Failed to allocate one structure field type.");
- goto error;
- }
-
- bt_field_type_structure_initialize((void *) structure,
- bt_field_type_structure_destroy_recursive,
- &bt_field_type_structure_methods);
- BT_LOGD("Created structure field type object: addr=%p",
- structure);
- goto end;
-
-error:
- BT_PUT(structure);
-
-end:
- return (void *) structure;
-}
-
-int bt_field_type_structure_add_field(struct bt_field_type *ft,
- struct bt_field_type *field_type,
- const char *field_name)
-{
- int ret = 0;
- struct bt_field_type_structure *struct_ft = (void *) 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_FIELD_TYPE_ID_STRUCT) {
- BT_LOGW("Invalid parameter: field type is not a structure field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_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;
-}
-
-int64_t bt_field_type_structure_get_field_count(struct bt_field_type *ft)
-{
- struct bt_field_type_structure *struct_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
- "Field type");
- return (int64_t) struct_ft->fields->len;
-}
-
-int bt_field_type_structure_borrow_field_by_index(
- struct bt_field_type *ft,
- const char **field_name,
- struct bt_field_type **field_type, uint64_t index)
-{
- struct bt_field_type_structure *struct_ft = (void *) ft;
- struct bt_field_type_structure_field *field;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
- "Field type");
- BT_ASSERT_PRE(index < struct_ft->fields->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u, %![ft-]+F",
- index, struct_ft->fields->len, ft);
- field = BT_FIELD_TYPE_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;
-}
-
-struct bt_field_type *bt_field_type_structure_borrow_field_type_by_name(
- struct bt_field_type *ft, const char *name)
-{
- size_t index;
- GQuark name_quark;
- struct bt_field_type_structure_field *field;
- struct bt_field_type_structure *struct_ft = (void *) ft;
- struct bt_field_type *field_type = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_NON_NULL(name, "Name");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
- "Field type");
- name_quark = g_quark_try_string(name);
- if (!name_quark) {
- BT_LOGV("No such structure field type field name: "
- "ft-addr=%p, field-name=\"%s\"",
- 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_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(ft, index);
- field_type = field->type;
-
-end:
- return field_type;
-}
-
-struct bt_field_type *bt_field_type_variant_create(
- struct bt_field_type *tag_ft, const char *tag_name)
-{
- struct bt_field_type_variant *var_ft = NULL;
-
- BT_LOGD("Creating variant field type object: "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- tag_ft, tag_name);
-
- if (tag_name && !bt_identifier_is_valid(tag_name)) {
- BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- tag_ft, tag_name);
- goto error;
- }
-
- var_ft = g_new0(struct bt_field_type_variant, 1);
- if (!var_ft) {
- BT_LOGE_STR("Failed to allocate one variant field type.");
- goto error;
- }
-
- bt_field_type_variant_initialize((void *) var_ft,
- (void *) tag_ft, tag_name,
- bt_field_type_variant_destroy_recursive,
- &bt_field_type_variant_methods);
- BT_LOGD("Created variant field type object: addr=%p, "
- "tag-ft-addr=%p, tag-field-name=\"%s\"",
- var_ft, tag_ft, tag_name);
- goto end;
-
-error:
- BT_PUT(var_ft);
-
-end:
- return (void *) var_ft;
-}
-
-struct bt_field_type *bt_field_type_variant_borrow_tag_field_type(
- struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
- struct bt_field_type *tag_ft = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
-
- if (!var_ft->tag_ft) {
- BT_LOGV("Variant field type has no tag field type: "
- "addr=%p", ft);
- goto end;
- }
-
- tag_ft = (void *) var_ft->tag_ft;
-
-end:
- return tag_ft;
-}
-
-const char *bt_field_type_variant_get_tag_name(struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
- const char *tag_name = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
-
- if (var_ft->tag_name->len == 0) {
- BT_LOGV("Variant field type has no tag field name: "
- "addr=%p", ft);
- goto end;
- }
-
- tag_name = var_ft->tag_name->str;
-
-end:
- return tag_name;
-}
-
-int bt_field_type_variant_set_tag_name(
- struct bt_field_type *ft, const char *name)
-{
- int ret = 0;
- struct bt_field_type_variant *var_ft = (void *) 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_FIELD_TYPE_ID_VARIANT) {
- BT_LOGW("Invalid parameter: field type is not a variant field type: "
- "addr=%p, ft-id=%s", ft, bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
-
- if (!bt_identifier_is_valid(name)) {
- BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
- "variant-ft-addr=%p, tag-field-name=\"%s\"",
- 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;
-}
-
-int bt_field_type_variant_add_field(struct bt_field_type *ft,
- struct bt_field_type *field_type,
- const char *field_name)
-{
- size_t i;
- int ret = 0;
- struct bt_field_type_variant *var_ft = (void *) 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_FIELD_TYPE_ID_VARIANT) {
- BT_LOGW("Invalid parameter: field type is not a variant field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_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 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;
-}
-
-struct bt_field_type *bt_field_type_variant_borrow_field_type_by_name(
- struct bt_field_type *ft,
- const char *field_name)
-{
- size_t index;
- GQuark name_quark;
- struct bt_field_type_variant_choice *choice;
- struct bt_field_type_variant *var_ft = (void *) ft;
- struct bt_field_type *field_type = NULL;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_NON_NULL(field_name, "Name");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- name_quark = g_quark_try_string(field_name);
- if (!name_quark) {
- BT_LOGV("No such variant field type field name: "
- "ft-addr=%p, field-name=\"%s\"",
- 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_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(ft, index);
- field_type = choice->type;
-
-end:
- return field_type;
-}
-
-int64_t bt_field_type_variant_get_field_count(struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- return (int64_t) var_ft->choices->len;
-}
-
-int bt_field_type_variant_borrow_field_by_index(struct bt_field_type *ft,
- const char **field_name, struct bt_field_type **field_type,
- uint64_t index)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
- struct bt_field_type_variant_choice *choice;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- BT_ASSERT_PRE(index < var_ft->choices->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u, %![ft-]+F",
- index, var_ft->choices->len, ft);
- choice = BT_FIELD_TYPE_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_field_type_variant_find_choice_index(
- struct bt_field_type *ft, uint64_t uval,
- bool is_signed)
-{
- int64_t ret;
- uint64_t i;
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- BT_ASSERT(ft);
- BT_ASSERT(ft->id == BT_FIELD_TYPE_ID_VARIANT);
-
- if (bt_field_type_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_field_type_variant_choice *choice =
- BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
- var_ft, i);
-
- for (range_i = 0; range_i < choice->ranges->len; range_i++) {
- struct bt_field_type_variant_choice_range *range =
- &g_array_index(
- choice->ranges,
- struct bt_field_type_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;
-}
-
-struct bt_field_type *bt_field_type_array_create(
- struct bt_field_type *element_ft, unsigned int length)
-{
- struct bt_field_type_array *array = NULL;
-
- BT_LOGD("Creating array field type object: element-ft-addr=%p, "
- "length=%u", element_ft, length);
-
- if (!element_ft) {
- BT_LOGW_STR("Invalid parameter: element field type is NULL.");
- goto error;
- }
-
- if (length == 0) {
- BT_LOGW_STR("Invalid parameter: length is zero.");
- goto error;
- }
-
- array = g_new0(struct bt_field_type_array, 1);
- if (!array) {
- BT_LOGE_STR("Failed to allocate one array field type.");
- goto error;
- }
-
- bt_field_type_array_initialize((void *) array,
- (void *) element_ft, length,
- bt_field_type_array_destroy_recursive,
- &bt_field_type_array_methods);
- BT_LOGD("Created array field type object: addr=%p, "
- "element-ft-addr=%p, length=%u",
- array, element_ft, length);
- goto end;
-
-error:
- BT_PUT(array);
-
-end:
- return (void *) array;
-}
-
-struct bt_field_type *bt_field_type_array_borrow_element_field_type(
- struct bt_field_type *ft)
-{
- struct bt_field_type_array *array_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ARRAY,
- "Field type");
- BT_ASSERT(array_ft && array_ft->element_ft);
- return array_ft->element_ft;
-}
-
-int64_t bt_field_type_array_get_length(struct bt_field_type *ft)
-{
- struct bt_field_type_array *array_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_ARRAY,
- "Field type");
- return (int64_t) array_ft->length;
-}
-
-struct bt_field_type *bt_field_type_sequence_create(
- struct bt_field_type *element_ft,
- const char *length_field_name)
-{
- struct bt_field_type_sequence *sequence = NULL;
-
- BT_LOGD("Creating sequence field type object: element-ft-addr=%p, "
- "length-field-name=\"%s\"", element_ft, length_field_name);
-
- if (!element_ft) {
- BT_LOGW_STR("Invalid parameter: element field type is NULL.");
- goto error;
- }
-
- if (!bt_identifier_is_valid(length_field_name)) {
- BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: "
- "length-field-name=\"%s\"", length_field_name);
- goto error;
- }
-
- sequence = g_new0(struct bt_field_type_sequence, 1);
- if (!sequence) {
- BT_LOGE_STR("Failed to allocate one sequence field type.");
- goto error;
- }
-
- bt_field_type_sequence_initialize((void *) sequence,
- (void *) element_ft, length_field_name,
- bt_field_type_sequence_destroy_recursive,
- &bt_field_type_sequence_methods);
- BT_LOGD("Created sequence field type object: addr=%p, "
- "element-ft-addr=%p, length-field-name=\"%s\"",
- sequence, element_ft, length_field_name);
- goto end;
-
-error:
- BT_PUT(sequence);
-
-end:
- return (void *) sequence;
-}
-
-struct bt_field_type *bt_field_type_sequence_borrow_element_field_type(
- struct bt_field_type *ft)
-{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
- "Field type");
- return seq_ft->element_ft;
-}
-
-const char *bt_field_type_sequence_get_length_field_name(
- struct bt_field_type *ft)
-{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
- "Field type");
- return seq_ft->length_field_name ?
- seq_ft->length_field_name->str : NULL;
-}
-
-struct bt_field_type *bt_field_type_string_create(void)
-{
- struct bt_field_type_string *string =
- g_new0(struct bt_field_type_string, 1);
-
- BT_LOGD_STR("Creating string field type object.");
-
- if (!string) {
- BT_LOGE_STR("Failed to allocate one string field type.");
- return NULL;
- }
-
- bt_field_type_string_initialize((void *) string,
- bt_field_type_string_destroy,
- &bt_field_type_string_methods);
- BT_LOGD("Created string field type object: addr=%p", string);
- return (void *) string;
-}
-
-enum bt_string_encoding bt_field_type_string_get_encoding(
- struct bt_field_type *ft)
-{
- struct bt_field_type_string *string_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRING,
- "Field type");
- return string_ft->encoding;
-}
-
-int bt_field_type_string_set_encoding(struct bt_field_type *ft,
- enum bt_string_encoding encoding)
-{
- int ret = 0;
- struct bt_field_type_string *string_ft = (void *) ft;
-
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
-
- if (ft->id != BT_FIELD_TYPE_ID_STRING) {
- BT_LOGW("Invalid parameter: field type is not a string field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
-
- if (encoding != BT_STRING_ENCODING_UTF8 &&
- encoding != BT_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_common_string_encoding_string(encoding));
-
-end:
- return ret;
-}
-
-int bt_field_type_get_alignment(struct bt_field_type *ft)
-{
- int ret;
- enum bt_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_field_type_get_type_id(ft);
- switch (type_id) {
- case BT_FIELD_TYPE_ID_SEQUENCE:
- {
- struct bt_field_type *element_ft =
- bt_field_type_sequence_borrow_element_field_type(ft);
-
- BT_ASSERT(element_ft);
- ret = bt_field_type_get_alignment(element_ft);
- break;
- }
- case BT_FIELD_TYPE_ID_ARRAY:
- {
- struct bt_field_type *element_ft =
- bt_field_type_array_borrow_element_field_type(ft);
-
- BT_ASSERT(element_ft);
- ret = bt_field_type_get_alignment(element_ft);
- break;
- }
- case BT_FIELD_TYPE_ID_STRUCT:
- {
- int64_t i, element_count;
-
- element_count = bt_field_type_structure_get_field_count(
- ft);
- BT_ASSERT(element_count >= 0);
-
- for (i = 0; i < element_count; i++) {
- struct bt_field_type *field = NULL;
- int field_alignment;
-
- ret = bt_field_type_structure_borrow_field_by_index(
- ft, NULL, &field, i);
- BT_ASSERT(ret == 0);
- BT_ASSERT(field);
- field_alignment = bt_field_type_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_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;
-}
-
-int bt_field_type_set_alignment(struct bt_field_type *ft,
- unsigned int alignment)
-{
- int ret = 0;
- enum bt_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_field_type_get_type_id(ft);
- if (type_id == BT_FIELD_TYPE_ID_UNKNOWN) {
- BT_LOGW("Invalid parameter: unknown field type ID: "
- "addr=%p, ft-id=%d", ft, type_id);
- ret = -1;
- goto end;
- }
-
- if (ft->id == BT_FIELD_TYPE_ID_STRING && alignment != CHAR_BIT) {
- BT_LOGW("Invalid parameter: alignment must be %u for a string field type: "
- "addr=%p, align=%u", CHAR_BIT, ft, alignment);
- ret = -1;
- goto end;
- }
-
- if (type_id == BT_FIELD_TYPE_ID_VARIANT ||
- type_id == BT_FIELD_TYPE_ID_SEQUENCE ||
- type_id == BT_FIELD_TYPE_ID_ARRAY) {
- /* Setting an alignment on these types makes no sense */
- BT_LOGW("Invalid parameter: cannot set the alignment of this field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_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;
-}
-
-enum bt_byte_order bt_field_type_get_byte_order(struct bt_field_type *ft)
-{
- enum bt_byte_order ret = BT_BYTE_ORDER_UNKNOWN;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
-
- switch (ft->id) {
- case BT_FIELD_TYPE_ID_INTEGER:
- {
- struct bt_field_type_integer *integer = (void *) ft;
-
- ret = integer->user_byte_order;
- break;
- }
- case BT_FIELD_TYPE_ID_ENUM:
- {
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
-
- ret = bt_field_type_get_byte_order(
- (void *) enum_ft->container_ft);
- break;
- }
- case BT_FIELD_TYPE_ID_FLOAT:
- {
- struct bt_field_type_floating_point *floating_point = (void *) 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_common_field_type_id_string(ft->id));
- goto end;
- }
-
- BT_ASSERT(ret == BT_BYTE_ORDER_NATIVE ||
- ret == BT_BYTE_ORDER_LITTLE_ENDIAN ||
- ret == BT_BYTE_ORDER_BIG_ENDIAN ||
- ret == BT_BYTE_ORDER_NETWORK);
-
-end:
- return ret;
-}
-
-int bt_field_type_set_byte_order(struct bt_field_type *ft,
- enum bt_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_BYTE_ORDER_NATIVE &&
- byte_order != BT_BYTE_ORDER_LITTLE_ENDIAN &&
- byte_order != BT_BYTE_ORDER_BIG_ENDIAN &&
- byte_order != BT_BYTE_ORDER_NETWORK) {
- BT_LOGW("Invalid parameter: invalid byte order: "
- "addr=%p, bo=%s", ft,
- bt_common_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_common_byte_order_string(byte_order));
-
-end:
- return ret;
-}
-
-enum bt_field_type_id bt_field_type_get_type_id(struct bt_field_type *ft)
-{
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- return ft->id;
-}
-
-BT_HIDDEN
-void bt_field_type_freeze(struct bt_field_type *ft)
-{
- if (!ft || ft->frozen) {
- return;
- }
-
- BT_ASSERT(ft->methods->freeze);
- ft->methods->freeze(ft);
-}
-
-struct bt_field_type *bt_field_type_copy(struct bt_field_type *ft)
-{
- struct bt_field_type *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;
-}
-
-static inline
-int bt_field_type_structure_get_field_name_index(
- struct bt_field_type *ft, const char *name)
-{
- int ret;
- size_t index;
- GQuark name_quark;
- struct bt_field_type_structure *struct_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_NON_NULL(name, "Name");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
- "Field type");
-
- name_quark = g_quark_try_string(name);
- if (!name_quark) {
- BT_LOGV("No such structure field type field name: "
- "ft-addr=%p, field-name=\"%s\"",
- 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;
-}
-
-static inline
-int bt_field_type_variant_get_field_name_index(
- struct bt_field_type *ft, const char *name)
-{
- int ret;
- size_t index;
- GQuark name_quark;
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_NON_NULL(name, "Name");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- name_quark = g_quark_try_string(name);
- if (!name_quark) {
- BT_LOGV("No such variant field type field name: "
- "ft-addr=%p, field-name=\"%s\"",
- 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_field_type_sequence_set_length_field_path(
- struct bt_field_type *ft, struct bt_field_path *path)
-{
- int ret = 0;
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
-
- if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
- BT_LOGW("Invalid parameter: field type is not a sequence field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
-
- bt_get(path);
- BT_MOVE(seq_ft->length_field_path, path);
- BT_LOGV("Set sequence field type's length field path: ft-addr=%p, "
- "field-path-addr=%p", ft, path);
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-int bt_field_type_variant_set_tag_field_path(
- struct bt_field_type *ft,
- struct bt_field_path *path)
-{
- int ret = 0;
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- if (!ft) {
- BT_LOGW_STR("Invalid parameter: field type is NULL.");
- ret = -1;
- goto end;
- }
-
- if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
- BT_LOGW("Invalid parameter: field type is not a variant field type: "
- "addr=%p, ft-id=%s", ft,
- bt_common_field_type_id_string(ft->id));
- ret = -1;
- goto end;
- }
-
- bt_get(path);
- BT_MOVE(var_ft->tag_field_path, path);
- BT_LOGV("Set variant field type's tag field path: ft-addr=%p, "
- "field-path-addr=%p", ft, path);
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-int bt_field_type_variant_set_tag_field_type(
- struct bt_field_type *ft,
- struct bt_field_type *tag_ft)
-{
- int ret = 0;
- struct bt_field_type_variant *var_ft = (void *) 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_FIELD_TYPE_ID_ENUM) {
- BT_LOGW("Invalid parameter: tag field type is not an enumeration field type: "
- "addr=%p, ft-id=%s", tag_ft,
- bt_common_field_type_id_string(tag_ft->id));
- ret = -1;
- goto end;
- }
-
- bt_put(var_ft->tag_ft);
- var_ft->tag_ft = bt_get(tag_ft);
- BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, "
- "tag-ft-addr=%p", ft, tag_ft);
-
-end:
- return ret;
-}
-
-static
-void bt_field_type_generic_freeze(struct bt_field_type *ft)
-{
- ft->frozen = 1;
-}
-
-static
-void bt_field_type_enumeration_freeze_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
-
- BT_LOGD("Freezing enumeration field type object: addr=%p", ft);
- bt_field_type_enumeration_set_range_overlap(enum_ft);
- bt_field_type_generic_freeze(ft);
- BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
- enum_ft->container_ft);
- bt_field_type_freeze((void *) enum_ft->container_ft);
-}
-
-static
-void bt_field_type_structure_freeze_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type_structure *struct_ft = (void *) ft;
- uint64_t i;
-
- /* Cache the alignment */
- BT_LOGD("Freezing structure field type object: addr=%p", ft);
- ft->alignment = bt_field_type_get_alignment(ft);
- bt_field_type_generic_freeze(ft);
-
- for (i = 0; i < struct_ft->fields->len; i++) {
- struct bt_field_type_structure_field *field =
- BT_FIELD_TYPE_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_field_type_freeze(field->type);
- }
-}
-
-BT_HIDDEN
-int bt_field_type_variant_update_choices(struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) 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_field_type_variant_choice *choice =
- BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(ft, i);
- const char *choice_name = g_quark_to_string(choice->name);
- struct bt_field_type_enumeration_mapping_iterator *iter =
- bt_field_type_enumeration_find_mappings_by_name(
- (void *) 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_field_type_enumeration_mapping_iterator_next(iter) == 0) {
- struct bt_field_type_variant_choice_range range;
-
- if (is_signed) {
- ret = bt_field_type_enumeration_mapping_iterator_signed_get(
- iter, NULL,
- &range.lower.i, &range.upper.i);
- } else {
- ret = bt_field_type_enumeration_mapping_iterator_unsigned_get(
- iter, NULL,
- &range.lower.u, &range.upper.u);
- }
-
- BT_ASSERT(ret == 0);
- g_array_append_val(choice->ranges, range);
- }
-
- bt_put(iter);
- }
-
- var_ft->choices_up_to_date = true;
-
-end:
- return ret;
-}
-
-static
-void bt_field_type_variant_freeze_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
- uint64_t i;
-
- BT_LOGD("Freezing variant field type object: addr=%p", ft);
- bt_field_type_generic_freeze(ft);
-
- for (i = 0; i < var_ft->choices->len; i++) {
- struct bt_field_type_variant_choice *choice =
- BT_FIELD_TYPE_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_field_type_freeze(choice->type);
- }
-}
-
-static
-void bt_field_type_array_freeze_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type_array *array_ft = (void *) ft;
-
- /* Cache the alignment */
- BT_LOGD("Freezing array field type object: addr=%p", ft);
- ft->alignment = bt_field_type_get_alignment(ft);
- bt_field_type_generic_freeze(ft);
- BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
- array_ft->element_ft);
- bt_field_type_freeze(array_ft->element_ft);
-}
-
-static
-void bt_field_type_sequence_freeze_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- /* Cache the alignment */
- BT_LOGD("Freezing sequence field type object: addr=%p", ft);
- ft->alignment = bt_field_type_get_alignment(ft);
- bt_field_type_generic_freeze(ft);
- BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
- seq_ft->element_ft);
- bt_field_type_freeze(seq_ft->element_ft);
-}
-
-static
-void bt_field_type_integer_set_byte_order(
- struct bt_field_type *ft, enum bt_byte_order byte_order)
-{
- struct bt_field_type_integer *int_ft = (void *) ft;
-
- int_ft->user_byte_order = byte_order;
-}
-
-static
-void bt_field_type_enumeration_set_byte_order_recursive(
- struct bt_field_type *ft, enum bt_byte_order byte_order)
-{
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
-
- bt_field_type_set_byte_order((void *) enum_ft->container_ft,
- byte_order);
-}
-
-static
-void bt_field_type_floating_point_set_byte_order(
- struct bt_field_type *ft, enum bt_byte_order byte_order)
-{
- struct bt_field_type_floating_point *flt_ft = (void *) ft;
-
- flt_ft->user_byte_order = byte_order;
-}
-
-static
-void bt_field_type_structure_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order)
-{
- int i;
- struct bt_field_type_structure *struct_ft = (void *) ft;
-
- for (i = 0; i < struct_ft->fields->len; i++) {
- struct bt_field_type_structure_field *field =
- BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
- struct_ft, i);
- struct bt_field_type *field_type = field->type;
-
- bt_field_type_set_byte_order(field_type, byte_order);
- }
-}
-
-static
-void bt_field_type_variant_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order)
-{
- int i;
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- for (i = 0; i < var_ft->choices->len; i++) {
- struct bt_field_type_variant_choice *choice =
- BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
- var_ft, i);
- struct bt_field_type *field_type = choice->type;
-
- bt_field_type_set_byte_order(field_type, byte_order);
- }
-}
-
-static
-void bt_field_type_array_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order)
-{
- struct bt_field_type_array *array_ft = (void *) ft;
-
- bt_field_type_set_byte_order(array_ft->element_ft, byte_order);
-}
-
-static
-void bt_field_type_sequence_set_byte_order_recursive(
- struct bt_field_type *ft,
- enum bt_byte_order byte_order)
-{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- bt_field_type_set_byte_order(seq_ft->element_ft, byte_order);
-}
-
-
-static
-int bt_field_type_integer_compare(struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- struct bt_field_type_integer *int_ft_a = (void *) ft_a;
- struct bt_field_type_integer *int_ft_b = (void *) 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_common_byte_order_string(int_ft_a->user_byte_order),
- bt_common_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_common_integer_base_string(int_ft_a->base),
- bt_common_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_common_string_encoding_string(int_ft_a->encoding),
- bt_common_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_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;
-}
-
-static
-int bt_field_type_floating_point_compare(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- struct bt_field_type_floating_point *flt_ft_a = (void *) ft_a;
- struct bt_field_type_floating_point *flt_ft_b = (void *) ft_b;
-
- /* Byte order */
- if (flt_ft_a->user_byte_order != flt_ft_b->user_byte_order) {
- BT_LOGV("Floating point number field types differ: different byte orders: "
- "ft-a-bo=%s, ft-b-bo=%s",
- bt_common_byte_order_string(flt_ft_a->user_byte_order),
- bt_common_byte_order_string(flt_ft_b->user_byte_order));
- goto end;
- }
-
- /* 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 enumeration_mapping *mapping_a,
- struct 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;
-}
-
-static
-int bt_field_type_enumeration_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- int i;
- struct bt_field_type_enumeration *enum_ft_a = (void *) ft_a;
- struct bt_field_type_enumeration *enum_ft_b = (void *) ft_b;
-
- /* Container field type */
- ret = bt_field_type_compare((void *) enum_ft_a->container_ft,
- (void *) 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 enumeration_mapping *mapping_a =
- g_ptr_array_index(enum_ft_a->entries, i);
- struct enumeration_mapping *mapping_b =
- g_ptr_array_index(enum_ft_b->entries, i);
-
- 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;
-}
-
-static
-int bt_field_type_string_compare(struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- struct bt_field_type_string *string_ft_a = (void *) ft_a;
- struct bt_field_type_string *string_ft_b = (void *) 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_common_string_encoding_string(string_ft_a->encoding),
- bt_common_string_encoding_string(string_ft_b->encoding));
- goto end;
- }
-
- /* Equal */
- ret = 0;
-
-end:
- return ret;
-}
-
-static
-int compare_structure_variant_members(
- struct bt_field_type *member_a_ft,
- struct bt_field_type *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_field_type_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;
-}
-
-static
-int bt_field_type_structure_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- int i;
- struct bt_field_type_structure *struct_ft_a = (void *) ft_a;
- struct bt_field_type_structure *struct_ft_b = (void *) ft_b;
-
- /* Alignment */
- if (bt_field_type_get_alignment(ft_a) !=
- bt_field_type_get_alignment(ft_b)) {
- BT_LOGV("Structure field types differ: different alignments: "
- "ft-a-align=%u, ft-b-align=%u",
- bt_field_type_get_alignment(ft_a),
- bt_field_type_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_field_type_structure_field *field_a =
- BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
- struct_ft_a, i);
- struct bt_field_type_structure_field *field_b =
- BT_FIELD_TYPE_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;
-}
-
-static
-int bt_field_type_variant_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- int i;
- struct bt_field_type_variant *var_ft_a = (void *) ft_a;
- struct bt_field_type_variant *var_ft_b = (void *) 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_field_type_compare((void *) var_ft_a->tag_ft,
- (void *) 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_field_type_variant_choice *choice_a =
- BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
- var_ft_a, i);
- struct bt_field_type_variant_choice *choice_b =
- BT_FIELD_TYPE_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;
-}
-
-static
-int bt_field_type_array_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = 1;
- struct bt_field_type_array *array_ft_a = (void *) ft_a;
- struct bt_field_type_array *array_ft_b = (void *) 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_field_type_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;
-}
-
-static
-int bt_field_type_sequence_compare_recursive(
- struct bt_field_type *ft_a,
- struct bt_field_type *ft_b)
-{
- int ret = -1;
- struct bt_field_type_sequence *seq_ft_a = (void *) ft_a;
- struct bt_field_type_sequence *seq_ft_b = (void *) 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_field_type_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_field_type_compare(struct bt_field_type *ft_a,
- struct bt_field_type *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_common_field_type_id_string(ft_a->id),
- bt_common_field_type_id_string(ft_b->id));
- goto end;
- }
-
- if (ft_a->id == BT_FIELD_TYPE_ID_UNKNOWN) {
- /* Both have unknown type IDs */
- BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
- goto end;
- }
-
- 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);
- }
+error:
+ BT_PUT(string_ft);
end:
- return ret;
-}
-
-BT_HIDDEN
-int64_t bt_field_type_get_field_count(struct bt_field_type *ft)
-{
- int64_t field_count = -1;
-
- switch (ft->id) {
- case BT_FIELD_TYPE_ID_STRUCT:
- field_count =
- bt_field_type_structure_get_field_count(ft);
- break;
- case BT_FIELD_TYPE_ID_VARIANT:
- field_count =
- bt_field_type_variant_get_field_count(ft);
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- case BT_FIELD_TYPE_ID_SEQUENCE:
- /*
- * Array and sequence types always contain a single member
- * (the element type).
- */
- field_count = 1;
- break;
- default:
- break;
- }
-
- return field_count;
+ return (void *) string_ft;
}
BT_HIDDEN
-struct bt_field_type *bt_field_type_borrow_field_at_index(
- struct bt_field_type *ft, int index)
+void _bt_field_type_freeze(struct bt_field_type *ft)
{
- struct bt_field_type *field_type = NULL;
-
- switch (ft->id) {
- case BT_FIELD_TYPE_ID_STRUCT:
- {
- int ret = bt_field_type_structure_borrow_field_by_index(
- ft, NULL, &field_type, index);
- if (ret) {
- field_type = NULL;
- goto end;
- }
- break;
- }
- case BT_FIELD_TYPE_ID_VARIANT:
- {
- int ret = bt_field_type_variant_borrow_field_by_index(
- ft, NULL, &field_type, index);
- if (ret) {
- field_type = NULL;
- goto end;
- }
- break;
- }
- case BT_FIELD_TYPE_ID_ARRAY:
- field_type =
- bt_field_type_array_borrow_element_field_type(ft);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- field_type =
- bt_field_type_sequence_borrow_element_field_type(ft);
- break;
- default:
- break;
- }
-
-end:
- return field_type;
+ /*
+ * Element/member/option field types are frozen when added to
+ * their owner.
+ */
+ BT_ASSERT(ft);
+ ft->frozen = true;
}
BT_HIDDEN
-int bt_field_type_get_field_index(struct bt_field_type *ft,
- const char *name)
+void _bt_field_type_make_part_of_trace(struct bt_field_type *ft)
{
- int field_index = -1;
+ BT_ASSERT(ft);
+ BT_ASSERT_PRE(!ft->part_of_trace,
+ "Field type is already part of a trace: %!+F", ft);
+ ft->part_of_trace = true;
switch (ft->id) {
- case BT_FIELD_TYPE_ID_STRUCT:
- field_index = bt_field_type_structure_get_field_name_index(
- ft, name);
- break;
+ case BT_FIELD_TYPE_ID_STRUCTURE:
case BT_FIELD_TYPE_ID_VARIANT:
- field_index = bt_field_type_variant_get_field_name_index(
- ft, name);
- break;
- default:
- break;
- }
-
- return field_index;
-}
-
-struct bt_field_path *bt_field_type_variant_borrow_tag_field_path(
- struct bt_field_type *ft)
-{
- struct bt_field_type_variant *var_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
- "Field type");
- return var_ft->tag_field_path;
-}
-
-struct bt_field_path *bt_field_type_sequence_borrow_length_field_path(
- struct bt_field_type *ft)
-{
- struct bt_field_type_sequence *seq_ft = (void *) ft;
-
- BT_ASSERT_PRE_NON_NULL(ft, "Field type");
- BT_ASSERT_PRE_FT_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
- "Field type");
- return seq_ft->length_field_path;
-}
-
-BT_HIDDEN
-int bt_field_type_validate_single_clock_class(
- struct bt_field_type *ft,
- struct bt_clock_class **expected_clock_class)
-{
- int ret = 0;
-
- if (!ft) {
- goto end;
- }
-
- BT_ASSERT(expected_clock_class);
-
- switch (ft->id) {
- case BT_FIELD_TYPE_ID_INTEGER:
{
- struct bt_clock_class *mapped_clock_class =
- bt_field_type_integer_borrow_mapped_clock_class(ft);
+ struct bt_field_type_named_field_types_container *container_ft =
+ (void *) ft;
+ uint64_t i;
- if (!mapped_clock_class) {
- goto end;
- }
+ for (i = 0; i < container_ft->named_fts->len; i++) {
+ struct bt_named_field_type *named_ft =
+ BT_FIELD_TYPE_NAMED_FT_AT_INDEX(
+ container_ft, i);
- if (!*expected_clock_class) {
- /* Move reference to output parameter */
- *expected_clock_class = bt_get(mapped_clock_class);
- mapped_clock_class = NULL;
- BT_LOGV("Setting expected clock class: "
- "expected-clock-class-addr=%p",
- *expected_clock_class);
- } else {
- if (mapped_clock_class != *expected_clock_class) {
- BT_LOGW("Integer field type is not mapped to "
- "the expected clock class: "
- "mapped-clock-class-addr=%p, "
- "mapped-clock-class-name=\"%s\", "
- "expected-clock-class-addr=%p, "
- "expected-clock-class-name=\"%s\"",
- mapped_clock_class,
- bt_clock_class_get_name(mapped_clock_class),
- *expected_clock_class,
- bt_clock_class_get_name(*expected_clock_class));
- bt_put(mapped_clock_class);
- ret = -1;
- goto end;
- }
+ bt_field_type_make_part_of_trace(named_ft->ft);
}
break;
}
- case BT_FIELD_TYPE_ID_ENUM:
- case BT_FIELD_TYPE_ID_ARRAY:
- case BT_FIELD_TYPE_ID_SEQUENCE:
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
{
- struct bt_field_type *sub_ft = NULL;
-
- switch (ft->id) {
- case BT_FIELD_TYPE_ID_ENUM:
- sub_ft = bt_field_type_enumeration_borrow_container_field_type(
- ft);
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- sub_ft = bt_field_type_array_borrow_element_field_type(
- ft);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- sub_ft = bt_field_type_sequence_borrow_element_field_type(
- ft);
- break;
- default:
- BT_LOGF("Unexpected field type ID: id=%d", ft->id);
- abort();
- }
+ struct bt_field_type_array *array_ft = (void *) ft;
- BT_ASSERT(sub_ft);
- ret = bt_field_type_validate_single_clock_class(sub_ft,
- expected_clock_class);
- break;
- }
- case BT_FIELD_TYPE_ID_STRUCT:
- {
- uint64_t i;
- int64_t count = bt_field_type_structure_get_field_count(
- ft);
-
- for (i = 0; i < count; i++) {
- const char *name;
- struct bt_field_type *member_type;
-
- ret = bt_field_type_structure_borrow_field_by_index(
- ft, &name, &member_type, i);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_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_FIELD_TYPE_ID_VARIANT:
- {
- uint64_t i;
- int64_t count = bt_field_type_variant_get_field_count(
- ft);
-
- for (i = 0; i < count; i++) {
- const char *name;
- struct bt_field_type *member_type;
-
- ret = bt_field_type_variant_borrow_field_by_index(
- ft, &name, &member_type, i);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_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;
- }
- }
+ bt_field_type_make_part_of_trace(array_ft->element_ft);
break;
}
default:
break;
}
-
-end:
- return ret;
-}
-
-static
-struct bt_field_type *bt_field_type_integer_copy(
- struct bt_field_type *ft)
-{
- struct bt_field_type_integer *int_ft = (void *) ft;
- struct bt_field_type_integer *copy_ft;
-
- BT_LOGD("Copying integer field type's: addr=%p", ft);
- copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create integer field type.");
- goto end;
- }
-
- copy_ft->mapped_clock_class = bt_get(int_ft->mapped_clock_class);
- copy_ft->user_byte_order = int_ft->user_byte_order;
- copy_ft->is_signed = int_ft->is_signed;
- copy_ft->size = int_ft->size;
- copy_ft->base = int_ft->base;
- copy_ft->encoding = int_ft->encoding;
- BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-}
-
-static
-struct bt_field_type *bt_field_type_enumeration_copy_recursive(
- struct bt_field_type *ft)
-{
- size_t i;
- struct bt_field_type_enumeration *enum_ft = (void *) ft;
- struct bt_field_type_enumeration *copy_ft = NULL;
- struct bt_field_type_enumeration *container_copy_ft;
-
- BT_LOGD("Copying enumeration field type's: addr=%p", ft);
-
- /* Copy the source enumeration's container */
- BT_LOGD_STR("Copying enumeration field type's container field type.");
- container_copy_ft =
- (void *) bt_field_type_copy((void *) enum_ft->container_ft);
- if (!container_copy_ft) {
- BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
- goto end;
- }
-
- copy_ft = (void *) bt_field_type_enumeration_create(
- (void *) container_copy_ft);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create enumeration field type.");
- goto end;
- }
-
- /* Copy all enumaration entries */
- for (i = 0; i < enum_ft->entries->len; i++) {
- struct enumeration_mapping *mapping = g_ptr_array_index(
- enum_ft->entries, i);
- struct enumeration_mapping *copy_mapping = g_new0(
- struct enumeration_mapping, 1);
-
- if (!copy_mapping) {
- BT_LOGE_STR("Failed to allocate one enumeration mapping.");
- goto error;
- }
-
- *copy_mapping = *mapping;
- g_ptr_array_add(copy_ft->entries, copy_mapping);
- }
-
- BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_put(container_copy_ft);
- return (void *) copy_ft;
-
-error:
- bt_put(container_copy_ft);
- BT_PUT(copy_ft);
- return (void *) copy_ft;
-}
-
-static
-struct bt_field_type *bt_field_type_floating_point_copy(
- struct bt_field_type *ft)
-{
- struct bt_field_type_floating_point *flt_ft = (void *) ft;
- struct bt_field_type_floating_point *copy_ft;
-
- BT_LOGD("Copying floating point number field type's: addr=%p", ft);
- copy_ft = (void *) bt_field_type_floating_point_create();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create 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 floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-}
-
-static
-struct bt_field_type *bt_field_type_structure_copy_recursive(
- struct bt_field_type *ft)
-{
- int64_t i;
- GHashTableIter iter;
- gpointer key, value;
- struct bt_field_type_structure *struct_ft = (void *) ft;
- struct bt_field_type_structure *copy_ft;
-
- BT_LOGD("Copying structure field type's: addr=%p", ft);
- copy_ft = (void *) bt_field_type_structure_create();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create 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_field_type_structure_field *entry, *copy_entry;
- struct bt_field_type *field_ft_copy;
-
- entry = BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
- struct_ft, i);
- copy_entry = BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
- copy_ft, i);
- BT_LOGD("Copying structure field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
-
- field_ft_copy = (void *) bt_field_type_copy(
- (void *) entry->type);
- if (!field_ft_copy) {
- BT_LOGE("Cannot copy structure field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
- goto error;
- }
-
- copy_entry->name = entry->name;
- copy_entry->type = field_ft_copy;
- }
-
- BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
-
-error:
- BT_PUT(copy_ft);
- return NULL;
-}
-
-static
-struct bt_field_type *bt_field_type_variant_copy_recursive(
- struct bt_field_type *ft)
-{
- int64_t i;
- GHashTableIter iter;
- gpointer key, value;
- struct bt_field_type *tag_ft_copy = NULL;
- struct bt_field_type_variant *var_ft = (void *) ft;
- struct bt_field_type_variant *copy_ft = NULL;
-
- BT_LOGD("Copying variant field type's: addr=%p", ft);
- if (var_ft->tag_ft) {
- BT_LOGD_STR("Copying variant field type's tag field type.");
- tag_ft_copy = bt_field_type_copy((void *) var_ft->tag_ft);
- if (!tag_ft_copy) {
- BT_LOGE_STR("Cannot copy variant field type's tag field type.");
- goto end;
- }
- }
-
- copy_ft = (void *) bt_field_type_variant_create(
- (void *) tag_ft_copy,
- var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create 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_field_type_variant_choice *entry, *copy_entry;
- struct bt_field_type *field_ft_copy;
- uint64_t range_i;
-
- entry = BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(var_ft, i);
- copy_entry = BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
- copy_ft, i);
- BT_LOGD("Copying variant field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
-
- field_ft_copy = (void *) bt_field_type_copy(
- (void *) entry->type);
- if (!field_ft_copy) {
- BT_LOGE("Cannot copy variant field type's field: "
- "index=%" PRId64 ", "
- "field-ft-addr=%p, field-name=\"%s\"",
- i, entry, g_quark_to_string(entry->name));
- g_free(copy_entry);
- goto error;
- }
-
- copy_entry->name = entry->name;
- copy_entry->type = field_ft_copy;
-
- /* Copy ranges */
- copy_entry->ranges = g_array_new(FALSE, TRUE,
- sizeof(struct bt_field_type_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 variant field type's tag field path.");
- copy_ft->tag_field_path = bt_field_path_copy(
- var_ft->tag_field_path);
- if (!copy_ft->tag_field_path) {
- BT_LOGE_STR("Cannot copy variant field type's tag field path.");
- goto error;
- }
- }
-
- copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
- BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_put(tag_ft_copy);
- return (void *) copy_ft;
-
-error:
- bt_put(tag_ft_copy);
- BT_PUT(copy_ft);
- return NULL;
-}
-
-static
-struct bt_field_type *bt_field_type_array_copy_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type *container_ft_copy = NULL;
- struct bt_field_type_array *array_ft = (void *) ft;
- struct bt_field_type_array *copy_ft = NULL;
-
- BT_LOGD("Copying array field type's: addr=%p", ft);
- BT_LOGD_STR("Copying array field type's element field type.");
- container_ft_copy = bt_field_type_copy(array_ft->element_ft);
- if (!container_ft_copy) {
- BT_LOGE_STR("Cannot copy array field type's element field type.");
- goto end;
- }
-
- copy_ft = (void *) bt_field_type_array_create(
- (void *) container_ft_copy, array_ft->length);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create array field type.");
- goto end;
- }
-
- BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_put(container_ft_copy);
- return (void *) copy_ft;
-}
-
-static
-struct bt_field_type *bt_field_type_sequence_copy_recursive(
- struct bt_field_type *ft)
-{
- struct bt_field_type *container_ft_copy = NULL;
- struct bt_field_type_sequence *seq_ft = (void *) ft;
- struct bt_field_type_sequence *copy_ft = NULL;
-
- BT_LOGD("Copying sequence field type's: addr=%p", ft);
- BT_LOGD_STR("Copying sequence field type's element field type.");
- container_ft_copy = bt_field_type_copy(seq_ft->element_ft);
- if (!container_ft_copy) {
- BT_LOGE_STR("Cannot copy sequence field type's element field type.");
- goto end;
- }
-
- copy_ft = (void *) bt_field_type_sequence_create(
- (void *) container_ft_copy,
- seq_ft->length_field_name->len ?
- seq_ft->length_field_name->str : NULL);
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create sequence field type.");
- goto end;
- }
-
- if (seq_ft->length_field_path) {
- BT_LOGD_STR("Copying sequence field type's length field path.");
- copy_ft->length_field_path = bt_field_path_copy(
- seq_ft->length_field_path);
- if (!copy_ft->length_field_path) {
- BT_LOGE_STR("Cannot copy sequence field type's length field path.");
- goto error;
- }
- }
-
- BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- bt_put(container_ft_copy);
- return (void *) copy_ft;
-error:
- bt_put(container_ft_copy);
- BT_PUT(copy_ft);
- return NULL;
-}
-
-static
-struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft)
-{
- struct bt_field_type_string *string_ft = (void *) ft;
- struct bt_field_type_string *copy_ft = NULL;
-
- BT_LOGD("Copying string field type's: addr=%p", ft);
- copy_ft = (void *) bt_field_type_string_create();
- if (!copy_ft) {
- BT_LOGE_STR("Cannot create string field type.");
- goto end;
- }
-
- copy_ft->encoding = string_ft->encoding;
- BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
- ft, copy_ft);
-
-end:
- return (void *) copy_ft;
}
if (field_wrapper->field) {
BT_LOGD_STR("Destroying field.");
- bt_field_destroy_recursive((void *) field_wrapper->field);
+ bt_field_destroy((void *) field_wrapper->field);
}
BT_LOGD_STR("Putting stream class.");
}
if (!field_wrapper->field) {
- field_wrapper->field = (void *) bt_field_create_recursive(ft);
+ field_wrapper->field = (void *) bt_field_create(ft);
if (!field_wrapper->field) {
BT_LIB_LOGE("Cannot create field wrapper from field type: "
"%![ft-]+F", ft);
#include <babeltrace/assert-internal.h>
#include <inttypes.h>
-#define BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(_field, _name) \
- BT_ASSERT_PRE((_field)->type->id == BT_FIELD_TYPE_ID_INTEGER || \
- (_field)->type->id == BT_FIELD_TYPE_ID_ENUM, \
- _name " is not an integer or an enumeration field: " \
- "%!+f", (_field))
-
-static
-int bt_field_generic_validate(struct bt_field *field);
-
-static
-int bt_field_structure_validate_recursive(struct bt_field *field);
-
-static
-int bt_field_variant_validate_recursive(struct bt_field *field);
-
-static
-int bt_field_array_validate_recursive(struct bt_field *field);
-
-static
-int bt_field_sequence_validate_recursive(struct bt_field *field);
-
-static
-void bt_field_generic_reset(struct bt_field *field);
-
-static
-void bt_field_structure_reset_recursive(struct bt_field *field);
-
static
-void bt_field_variant_reset_recursive(struct bt_field *field);
+void reset_single_field(struct bt_field *field);
static
-void bt_field_array_reset_recursive(struct bt_field *field);
+void reset_array_field(struct bt_field *field);
static
-void bt_field_sequence_reset_recursive(struct bt_field *field);
+void reset_structure_field(struct bt_field *field);
static
-void bt_field_generic_set_is_frozen(struct bt_field *field,
- bool is_frozen);
+void reset_variant_field(struct bt_field *field);
static
-void bt_field_structure_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen);
+void set_single_field_is_frozen(struct bt_field *field, bool is_frozen);
static
-void bt_field_variant_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen);
+void set_array_field_is_frozen(struct bt_field *field, bool is_frozen);
static
-void bt_field_array_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen);
+void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen);
static
-void bt_field_sequence_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen);
+void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen);
static
-bt_bool bt_field_generic_is_set(struct bt_field *field);
+bool single_field_is_set(struct bt_field *field);
static
-bt_bool bt_field_structure_is_set_recursive(
- struct bt_field *field);
+bool array_field_is_set(struct bt_field *field);
static
-bt_bool bt_field_variant_is_set_recursive(struct bt_field *field);
+bool structure_field_is_set(struct bt_field *field);
static
-bt_bool bt_field_array_is_set_recursive(struct bt_field *field);
+bool variant_field_is_set(struct bt_field *field);
static
-bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field);
-
-static struct bt_field_methods bt_field_integer_methods = {
- .set_is_frozen = bt_field_generic_set_is_frozen,
- .validate = bt_field_generic_validate,
- .is_set = bt_field_generic_is_set,
- .reset = bt_field_generic_reset,
+struct bt_field_methods integer_field_methods = {
+ .set_is_frozen = set_single_field_is_frozen,
+ .is_set = single_field_is_set,
+ .reset = reset_single_field,
};
-static struct bt_field_methods bt_field_floating_point_methods = {
- .set_is_frozen = bt_field_generic_set_is_frozen,
- .validate = bt_field_generic_validate,
- .is_set = bt_field_generic_is_set,
- .reset = bt_field_generic_reset,
-};
-
-static struct bt_field_methods bt_field_enumeration_methods = {
- .set_is_frozen = bt_field_generic_set_is_frozen,
- .validate = bt_field_generic_validate,
- .is_set = bt_field_generic_is_set,
- .reset = bt_field_generic_reset,
-};
-
-static struct bt_field_methods bt_field_string_methods = {
- .set_is_frozen = bt_field_generic_set_is_frozen,
- .validate = bt_field_generic_validate,
- .is_set = bt_field_generic_is_set,
- .reset = bt_field_generic_reset,
-};
-
-static struct bt_field_methods bt_field_structure_methods = {
- .set_is_frozen = bt_field_structure_set_is_frozen_recursive,
- .validate = bt_field_structure_validate_recursive,
- .is_set = bt_field_structure_is_set_recursive,
- .reset = bt_field_structure_reset_recursive,
+static
+struct bt_field_methods real_field_methods = {
+ .set_is_frozen = set_single_field_is_frozen,
+ .is_set = single_field_is_set,
+ .reset = reset_single_field,
};
-static struct bt_field_methods bt_field_sequence_methods = {
- .set_is_frozen = bt_field_sequence_set_is_frozen_recursive,
- .validate = bt_field_sequence_validate_recursive,
- .is_set = bt_field_sequence_is_set_recursive,
- .reset = bt_field_sequence_reset_recursive,
+static
+struct bt_field_methods string_field_methods = {
+ .set_is_frozen = set_single_field_is_frozen,
+ .is_set = single_field_is_set,
+ .reset = reset_single_field,
};
-static struct bt_field_methods bt_field_array_methods = {
- .set_is_frozen = bt_field_array_set_is_frozen_recursive,
- .validate = bt_field_array_validate_recursive,
- .is_set = bt_field_array_is_set_recursive,
- .reset = bt_field_array_reset_recursive,
+static
+struct bt_field_methods structure_field_methods = {
+ .set_is_frozen = set_structure_field_is_frozen,
+ .is_set = structure_field_is_set,
+ .reset = reset_structure_field,
};
-static struct bt_field_methods bt_field_variant_methods = {
- .set_is_frozen = bt_field_variant_set_is_frozen_recursive,
- .validate = bt_field_variant_validate_recursive,
- .is_set = bt_field_variant_is_set_recursive,
- .reset = bt_field_variant_reset_recursive,
+static
+struct bt_field_methods array_field_methods = {
+ .set_is_frozen = set_array_field_is_frozen,
+ .is_set = array_field_is_set,
+ .reset = reset_array_field,
};
static
-struct bt_field *bt_field_integer_create(struct bt_field_type *);
+struct bt_field_methods variant_field_methods = {
+ .set_is_frozen = set_variant_field_is_frozen,
+ .is_set = variant_field_is_set,
+ .reset = reset_variant_field,
+};
static
-struct bt_field *bt_field_enumeration_create(struct bt_field_type *);
+struct bt_field *create_integer_field(struct bt_field_type *);
static
-struct bt_field *bt_field_floating_point_create(struct bt_field_type *);
+struct bt_field *create_real_field(struct bt_field_type *);
static
-struct bt_field *bt_field_structure_create(struct bt_field_type *);
+struct bt_field *create_string_field(struct bt_field_type *);
static
-struct bt_field *bt_field_variant_create(struct bt_field_type *);
+struct bt_field *create_structure_field(struct bt_field_type *);
static
-struct bt_field *bt_field_array_create(struct bt_field_type *);
+struct bt_field *create_static_array_field(struct bt_field_type *);
static
-struct bt_field *bt_field_sequence_create(struct bt_field_type *);
+struct bt_field *create_dynamic_array_field(struct bt_field_type *);
static
-struct bt_field *bt_field_string_create(struct bt_field_type *);
+struct bt_field *create_variant_field(struct bt_field_type *);
static
struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = {
- [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create,
- [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create,
- [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create,
- [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create,
- [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create,
- [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create,
- [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create,
- [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create,
+ [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = create_integer_field,
+ [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = create_integer_field,
+ [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = create_integer_field,
+ [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = create_integer_field,
+ [BT_FIELD_TYPE_ID_REAL] = create_real_field,
+ [BT_FIELD_TYPE_ID_STRING] = create_string_field,
+ [BT_FIELD_TYPE_ID_STRUCTURE] = create_structure_field,
+ [BT_FIELD_TYPE_ID_STATIC_ARRAY] = create_static_array_field,
+ [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = create_dynamic_array_field,
+ [BT_FIELD_TYPE_ID_VARIANT] = create_variant_field,
};
static
-void bt_field_integer_destroy(struct bt_field *field);
-
-static
-void bt_field_enumeration_destroy(struct bt_field *field);
-
-static
-void bt_field_floating_point_destroy(struct bt_field *field);
+void destroy_integer_field(struct bt_field *field);
static
-void bt_field_structure_destroy_recursive(struct bt_field *field);
+void destroy_real_field(struct bt_field *field);
static
-void bt_field_variant_destroy_recursive(struct bt_field *field);
+void destroy_string_field(struct bt_field *field);
static
-void bt_field_array_destroy_recursive(struct bt_field *field);
+void destroy_structure_field(struct bt_field *field);
static
-void bt_field_sequence_destroy_recursive(struct bt_field *field);
+void destroy_array_field(struct bt_field *field);
static
-void bt_field_string_destroy(struct bt_field *field);
+void destroy_variant_field(struct bt_field *field);
static
void (* const field_destroy_funcs[])(struct bt_field *) = {
- [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy,
- [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy,
- [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy,
- [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive,
- [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive,
- [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive,
- [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive,
- [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy,
+ [BT_FIELD_TYPE_ID_UNSIGNED_INTEGER] = destroy_integer_field,
+ [BT_FIELD_TYPE_ID_SIGNED_INTEGER] = destroy_integer_field,
+ [BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION] = destroy_integer_field,
+ [BT_FIELD_TYPE_ID_SIGNED_ENUMERATION] = destroy_integer_field,
+ [BT_FIELD_TYPE_ID_REAL] = destroy_real_field,
+ [BT_FIELD_TYPE_ID_STRING] = destroy_string_field,
+ [BT_FIELD_TYPE_ID_STRUCTURE] = destroy_structure_field,
+ [BT_FIELD_TYPE_ID_STATIC_ARRAY] = destroy_array_field,
+ [BT_FIELD_TYPE_ID_DYNAMIC_ARRAY] = destroy_array_field,
+ [BT_FIELD_TYPE_ID_VARIANT] = destroy_variant_field,
};
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
+struct bt_field_type *bt_field_borrow_type(struct bt_field *field)
{
- bool ret = true;
- int64_t min_value, max_value;
-
- min_value = -(1ULL << (size - 1));
- max_value = (1ULL << (size - 1)) - 1;
- if (value < min_value || value > max_value) {
- BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
- "min-value=%" PRId64 ", max-value=%" PRId64,
- value, min_value, max_value);
- ret = false;
- }
-
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ return field->type;
}
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
+enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
{
- bool ret = true;
- int64_t max_value;
-
- max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
- if (value > max_value) {
- BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
- "max-value=%" PRIu64,
- value, max_value);
- ret = false;
- }
-
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ return field->type->id;
}
BT_HIDDEN
-struct bt_field *bt_field_create_recursive(struct bt_field_type *type)
+struct bt_field *bt_field_create(struct bt_field_type *ft)
{
struct bt_field *field = NULL;
- enum bt_field_type_id type_id;
-
- BT_ASSERT_PRE_NON_NULL(type, "Field type");
- BT_ASSERT(bt_field_type_has_known_id((void *) type));
- BT_ASSERT_PRE(bt_field_type_validate((void *) type) == 0,
- "Field type is invalid: %!+F", type);
- type_id = bt_field_type_get_type_id(type);
- field = field_create_funcs[type_id](type);
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT(bt_field_type_has_known_id(ft));
+ field = field_create_funcs[ft->id](ft);
if (!field) {
+ BT_LIB_LOGE("Cannot create field object from field type: "
+ "%![ft-]+F", ft);
goto end;
}
- bt_field_type_freeze(type);
-
end:
return field;
}
-struct bt_field_type *bt_field_borrow_type(struct bt_field *field)
+static inline
+void init_field(struct bt_field *field, struct bt_field_type *ft,
+ struct bt_field_methods *methods)
{
- struct bt_field_type *ret = NULL;
-
- BT_ASSERT_PRE_NON_NULL(field, "Field");
- ret = field->type;
- return ret;
+ BT_ASSERT(field);
+ BT_ASSERT(ft);
+ bt_object_init_unique(&field->base);
+ field->methods = methods;
+ field->type = bt_get(ft);
}
-enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
+static
+struct bt_field *create_integer_field(struct bt_field_type *ft)
{
- BT_ASSERT_PRE_NON_NULL(field, "Field");
- return field->type->id;
+ struct bt_field_integer *int_field;
+
+ BT_LIB_LOGD("Creating integer field object: %![ft-]+F", ft);
+ int_field = g_new0(struct bt_field_integer, 1);
+ if (!int_field) {
+ BT_LOGE_STR("Failed to allocate one integer field.");
+ goto end;
+ }
+
+ init_field((void *) int_field, ft, &integer_field_methods);
+ BT_LIB_LOGD("Created integer field object: %!+f", int_field);
+
+end:
+ return (void *) int_field;
}
-int64_t bt_field_sequence_get_length(struct bt_field *field)
+static
+struct bt_field *create_real_field(struct bt_field_type *ft)
{
- struct bt_field_sequence *sequence = (void *) field;
+ struct bt_field_real *real_field;
- BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
- "Field");
- return (int64_t) sequence->length;
+ BT_LIB_LOGD("Creating real field object: %![ft-]+F", ft);
+ real_field = g_new0(struct bt_field_real, 1);
+ if (!real_field) {
+ BT_LOGE_STR("Failed to allocate one real field.");
+ goto end;
+ }
+
+ init_field((void *) real_field, ft, &real_field_methods);
+ BT_LIB_LOGD("Created real field object: %!+f", real_field);
+
+end:
+ return (void *) real_field;
}
-int bt_field_sequence_set_length(struct bt_field *field, uint64_t length)
+static
+struct bt_field *create_string_field(struct bt_field_type *ft)
{
- int ret = 0;
- struct bt_field_sequence *sequence = (void *) field;
+ struct bt_field_string *string_field;
- BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
- BT_ASSERT_PRE(((int64_t) length) >= 0,
- "Invalid sequence length (too large): length=%" PRId64,
- length);
- BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field");
+ BT_LIB_LOGD("Creating string field object: %![ft-]+F", ft);
+ string_field = g_new0(struct bt_field_string, 1);
+ if (!string_field) {
+ BT_LOGE_STR("Failed to allocate one string field.");
+ goto end;
+ }
- if (unlikely(length > sequence->elements->len)) {
- /* Make more room */
- struct bt_field_type_sequence *sequence_ft;
- uint64_t cur_len = sequence->elements->len;
- uint64_t i;
+ init_field((void *) string_field, ft, &string_field_methods);
+ string_field->buf = g_array_sized_new(FALSE, FALSE,
+ sizeof(char), 1);
+ if (!string_field->buf) {
+ BT_LOGE_STR("Failed to allocate a GArray.");
+ BT_PUT(string_field);
+ goto end;
+ }
- g_ptr_array_set_size(sequence->elements, length);
- sequence_ft = (void *) sequence->common.type;
+ g_array_index(string_field->buf, char, 0) = '\0';
+ BT_LIB_LOGD("Created string field object: %!+f", string_field);
- for (i = cur_len; i < sequence->elements->len; i++) {
- struct bt_field *elem_field =
- bt_field_create_recursive(
- sequence_ft->element_ft);
+end:
+ return (void *) string_field;
+}
- if (!elem_field) {
- ret = -1;
- goto end;
- }
+static inline
+int create_fields_from_named_field_types(
+ struct bt_field_type_named_field_types_container *ft,
+ GPtrArray **fields)
+{
+ int ret = 0;
+ uint64_t i;
- BT_ASSERT(!sequence->elements->pdata[i]);
- sequence->elements->pdata[i] = elem_field;
- }
+ *fields = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_field_destroy);
+ if (!*fields) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
+ ret = -1;
+ goto end;
}
- sequence->length = length;
+ g_ptr_array_set_size(*fields, ft->named_fts->len);
+
+ for (i = 0; i < ft->named_fts->len; i++) {
+ struct bt_field *field;
+ struct bt_named_field_type *named_ft =
+ BT_FIELD_TYPE_NAMED_FT_AT_INDEX(ft, i);
+
+ field = bt_field_create(named_ft->ft);
+ if (!field) {
+ BT_LIB_LOGE("Failed to create structure member or variant option field: "
+ "name=\"%s\", %![ft-]+F",
+ named_ft->name->str, named_ft->ft);
+ ret = -1;
+ goto end;
+ }
+
+ g_ptr_array_index(*fields, i) = field;
+ }
end:
return ret;
}
-struct bt_field *bt_field_structure_borrow_field_by_index(
- struct bt_field *field, uint64_t index)
+static
+struct bt_field *create_structure_field(struct bt_field_type *ft)
{
- struct bt_field_structure *structure = (void *) field;
+ struct bt_field_structure *struct_field;
- BT_ASSERT_PRE_NON_NULL(field, "Structure field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_STRUCT, "Field");
- BT_ASSERT_PRE(index < structure->fields->len,
- "Index is out of bound: %![struct-field-]+f, "
- "index=%" PRIu64 ", count=%u", field, index,
- structure->fields->len);
- return structure->fields->pdata[index];
-}
+ BT_LIB_LOGD("Creating structure field object: %![ft-]+F", ft);
+ struct_field = g_new0(struct bt_field_structure, 1);
+ if (!struct_field) {
+ BT_LOGE_STR("Failed to allocate one structure field.");
+ goto end;
+ }
-struct bt_field *bt_field_structure_borrow_field_by_name(
- struct bt_field *field, const char *name)
-{
- struct bt_field *ret = NULL;
- GQuark field_quark;
- struct bt_field_type_structure *structure_ft;
- struct bt_field_structure *structure = (void *) field;
- size_t index;
- GHashTable *field_name_to_index;
-
- BT_ASSERT_PRE_NON_NULL(field, "Structure field");
- BT_ASSERT_PRE_NON_NULL(name, "Field name");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_STRUCT, "Field");
- structure_ft = (void *) field->type;
- field_name_to_index = structure_ft->field_name_to_index;
- field_quark = g_quark_from_string(name);
- if (!g_hash_table_lookup_extended(field_name_to_index,
- GUINT_TO_POINTER(field_quark),
- NULL, (gpointer *) &index)) {
- BT_LOGV("Invalid parameter: no such field in structure field's type: "
- "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
- field, field->type, name);
- goto error;
+ init_field((void *) struct_field, ft, &structure_field_methods);
+
+ if (create_fields_from_named_field_types((void *) ft,
+ &struct_field->fields)) {
+ BT_LIB_LOGE("Cannot create structure member fields: "
+ "%![ft-]+F", ft);
+ BT_PUT(struct_field);
+ goto end;
}
- ret = structure->fields->pdata[index];
- BT_ASSERT(ret);
+ BT_LIB_LOGD("Created structure field object: %!+f", struct_field);
-error:
- return ret;
+end:
+ return (void *) struct_field;
}
-struct bt_field *bt_field_array_borrow_field(
- struct bt_field *field, uint64_t index)
+static
+struct bt_field *create_variant_field(struct bt_field_type *ft)
{
- struct bt_field_array *array = (void *) field;
+ struct bt_field_variant *var_field;
- BT_ASSERT_PRE_NON_NULL(field, "Array field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY,
- "Field");
- BT_ASSERT_PRE(index < array->elements->len,
- "Index is out of bound: %![array-field-]+f, "
- "index=%" PRIu64 ", count=%u", field,
- index, array->elements->len);
- return array->elements->pdata[(size_t) index];
-}
+ BT_LIB_LOGD("Creating variant field object: %![ft-]+F", ft);
+ var_field = g_new0(struct bt_field_variant, 1);
+ if (!var_field) {
+ BT_LOGE_STR("Failed to allocate one variant field.");
+ goto end;
+ }
-struct bt_field *bt_field_sequence_borrow_field(
- struct bt_field *field, uint64_t index)
-{
- struct bt_field_sequence *sequence = (void *) field;
+ init_field((void *) var_field, ft, &variant_field_methods);
- BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
- "Field");
- BT_ASSERT_PRE(index < sequence->length,
- "Index is out of bound: %![seq-field-]+f, "
- "index=%" PRIu64 ", count=%u", field, index,
- sequence->elements->len);
- return sequence->elements->pdata[(size_t) index];
-}
+ if (create_fields_from_named_field_types((void *) ft,
+ &var_field->fields)) {
+ BT_LIB_LOGE("Cannot create variant member fields: "
+ "%![ft-]+F", ft);
+ BT_PUT(var_field);
+ goto end;
+ }
-struct bt_field *bt_field_variant_borrow_current_field(
- struct bt_field *field)
-{
- struct bt_field_variant *variant = (void *) field;
+ BT_LIB_LOGD("Created variant field object: %!+f", var_field);
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
- "Variant field has no current field: %!+f", field);
- return variant->current_field;
+end:
+ return (void *) var_field;
}
static inline
-int bt_field_variant_set_tag(struct bt_field *field,
- uint64_t tag_uval, bool is_signed)
+int init_array_field_fields(struct bt_field_array *array_field)
{
int ret = 0;
- int64_t choice_index;
- struct bt_field_variant *variant = (void *) field;
-
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_VARIANT, "Field");
+ uint64_t i;
+ struct bt_field_type_array *array_ft;
- /* Find matching index in variant field's type */
- choice_index = bt_field_type_variant_find_choice_index(
- field->type, tag_uval, is_signed);
- if (choice_index < 0) {
+ BT_ASSERT(array_field);
+ array_ft = (void *) array_field->common.type;
+ array_field->fields = g_ptr_array_sized_new(array_field->length);
+ if (!array_field->fields) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
ret = -1;
goto end;
}
- /* Select corresponding field */
- BT_ASSERT(choice_index < variant->fields->len);
- variant->current_field = variant->fields->pdata[choice_index];
- variant->tag_value.u = tag_uval;
+ g_ptr_array_set_free_func(array_field->fields,
+ (GDestroyNotify) bt_field_destroy);
+ g_ptr_array_set_size(array_field->fields, array_field->length);
+
+ for (i = 0; i < array_field->length; i++) {
+ array_field->fields->pdata[i] = bt_field_create(
+ array_ft->element_ft);
+ if (!array_field->fields->pdata[i]) {
+ BT_LIB_LOGE("Cannot create array field's element field: "
+ "index=%" PRIu64 ", %![ft-]+F", i, array_ft);
+ ret = -1;
+ goto end;
+ }
+ }
end:
return ret;
}
-int bt_field_variant_set_tag_signed(struct bt_field *variant_field,
- int64_t tag)
+static
+struct bt_field *create_static_array_field(struct bt_field_type *ft)
{
- return bt_field_variant_set_tag((void *) variant_field,
- (uint64_t) tag, true);
-}
+ struct bt_field_type_static_array *array_ft = (void *) ft;
+ struct bt_field_array *array_field;
-int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field,
- uint64_t tag)
-{
- return bt_field_variant_set_tag((void *) variant_field,
- (uint64_t) tag, false);
-}
+ BT_LIB_LOGD("Creating static array field object: %![ft-]+F", ft);
+ array_field = g_new0(struct bt_field_array, 1);
+ if (!array_field) {
+ BT_LOGE_STR("Failed to allocate one static array field.");
+ goto end;
+ }
-int bt_field_variant_get_tag_signed(struct bt_field *field,
- int64_t *tag)
-{
- struct bt_field_variant *variant = (void *) field;
+ init_field((void *) array_field, ft, &array_field_methods);
+ array_field->length = array_ft->length;
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
- "Variant field has no current field: %!+f", field);
- *tag = variant->tag_value.i;
- return 0;
-}
+ if (init_array_field_fields(array_field)) {
+ BT_LIB_LOGE("Cannot create static array fields: "
+ "%![ft-]+F", ft);
+ BT_PUT(array_field);
+ goto end;
+ }
-int bt_field_variant_get_tag_unsigned(struct bt_field *field,
- uint64_t *tag)
-{
- struct bt_field_variant *variant = (void *) field;
+ BT_LIB_LOGD("Created static array field object: %!+f", array_field);
- BT_ASSERT_PRE_NON_NULL(field, "Variant field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_VARIANT, "Field");
- BT_ASSERT_PRE(variant->current_field,
- "Variant field has no current field: %!+f", field);
- *tag = variant->tag_value.u;
- return 0;
+end:
+ return (void *) array_field;
}
-struct bt_field_type_enumeration_mapping_iterator *
-bt_field_enumeration_get_mappings(struct bt_field *field)
+static
+struct bt_field *create_dynamic_array_field(struct bt_field_type *ft)
{
- struct bt_field_enumeration *enum_field = (void *) field;
- struct bt_field_type_enumeration *enum_type = NULL;
- struct bt_field_type_integer *integer_type = NULL;
- struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
+ struct bt_field_array *array_field;
- BT_ASSERT(field);
- BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_ENUM);
- BT_ASSERT(field->payload_set);
- BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID((struct bt_field *) field,
- BT_FIELD_TYPE_ID_ENUM, "Field");
- BT_ASSERT_PRE_FIELD_IS_SET((struct bt_field *) field,
- "Enumeration field");
- enum_type = (void *) field->type;
- integer_type = enum_type->container_ft;
-
- if (!integer_type->is_signed) {
- iter = bt_field_type_enumeration_unsigned_find_mappings_by_value(
- field->type,
- enum_field->common.payload.unsignd);
- } else {
- iter = bt_field_type_enumeration_signed_find_mappings_by_value(
- field->type,
- enum_field->common.payload.signd);
+ BT_LIB_LOGD("Creating dynamic array field object: %![ft-]+F", ft);
+ array_field = g_new0(struct bt_field_array, 1);
+ if (!array_field) {
+ BT_LOGE_STR("Failed to allocate one dynamic array field.");
+ goto end;
+ }
+
+ init_field((void *) array_field, ft, &array_field_methods);
+
+ if (init_array_field_fields(array_field)) {
+ BT_LIB_LOGE("Cannot create dynamic array fields: "
+ "%![ft-]+F", ft);
+ BT_PUT(array_field);
+ goto end;
}
- return iter;
+ BT_LIB_LOGD("Created dynamic array field object: %!+f", array_field);
+
+end:
+ return (void *) array_field;
}
-BT_ASSERT_PRE_FUNC
-static inline
-struct bt_field_type_integer *get_int_enum_int_ft(
- struct bt_field *field)
+int64_t bt_field_signed_integer_get_value(struct bt_field *field)
{
struct bt_field_integer *int_field = (void *) field;
- struct bt_field_type_integer *int_ft = NULL;
-
- if (int_field->common.type->id == BT_FIELD_TYPE_ID_INTEGER) {
- int_ft = (void *) int_field->common.type;
- } else if (int_field->common.type->id == BT_FIELD_TYPE_ID_ENUM) {
- struct bt_field_type_enumeration *enum_ft =
- (void *) int_field->common.type;
- int_ft = enum_ft->container_ft;
- } else {
- abort();
- }
- BT_ASSERT(int_ft);
- return int_ft;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field");
+ return int_field->value.i;
}
-int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value)
+void bt_field_signed_integer_set_value(struct bt_field *field, int64_t value)
{
- struct bt_field_integer *integer = (void *) field;
+ struct bt_field_integer *int_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "Integer/enumeration field");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_IS_SET(field,
- "Integer/enumeration field");
- BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field");
- BT_ASSERT_PRE(bt_field_type_integer_is_signed(
- (void *) get_int_enum_int_ft(field)),
- "Field's type is unsigned: %!+f", field);
- *value = integer->payload.signd;
- return 0;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SIGNED_INT(field, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
+ BT_ASSERT_PRE(bt_util_value_is_in_range_signed(
+ ((struct bt_field_type_integer *) field->type)->range, value),
+ "Value is out of bounds: value=%" PRId64 ", %![field-]+f, "
+ "%![ft-]+F", value, field, field->type);
+ int_field->value.i = value;
+ bt_field_set_single(field, true);
}
-int bt_field_integer_signed_set_value(struct bt_field *field, int64_t value)
+uint64_t bt_field_unsigned_integer_get_value(struct bt_field *field)
{
- int ret = 0;
- struct bt_field_integer *integer = (void *) field;
-
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
- BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field");
- BT_ASSERT_PRE(bt_field_type_integer_is_signed(
- (void *) get_int_enum_int_ft(field)),
- "Field's type is unsigned: %!+f", field);
- BT_ASSERT_PRE(value_is_in_range_signed(
- get_int_enum_int_ft(field)->size, value),
- "Value is out of bounds: value=%" PRId64 ", %![field-]+f",
- value, field);
- integer->payload.signd = value;
- bt_field_set(field, true);
- return ret;
+ struct bt_field_integer *int_field = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field");
+ return int_field->value.u;
}
-int bt_field_integer_unsigned_get_value(struct bt_field *field, uint64_t *value)
+void bt_field_unsigned_integer_set_value(struct bt_field *field,
+ uint64_t value)
{
- struct bt_field_integer *integer = (void *) field;
+ struct bt_field_integer *int_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
- BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field");
- BT_ASSERT_PRE(!bt_field_type_integer_is_signed(
- (void *) get_int_enum_int_ft(field)),
- "Field's type is signed: %!+f", field);
- *value = integer->payload.unsignd;
- return 0;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_UNSIGNED_INT(field, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
+ BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(
+ ((struct bt_field_type_integer *) field->type)->range, value),
+ "Value is out of bounds: value=%" PRIu64 ", %![field-]+f, "
+ "%![ft-]+F", value, field, field->type);
+ int_field->value.u = value;
+ bt_field_set_single(field, true);
}
-int bt_field_integer_unsigned_set_value(struct bt_field *field,
- uint64_t value)
+double bt_field_real_get_value(struct bt_field *field)
{
- struct bt_field_integer *integer = (void *) field;
-
- BT_ASSERT_PRE_NON_NULL(field, "Integer field");
- BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
- BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field");
- BT_ASSERT_PRE(!bt_field_type_integer_is_signed(
- (void *) get_int_enum_int_ft(field)),
- "Field's type is signed: %!+f", field);
- BT_ASSERT_PRE(value_is_in_range_unsigned(
- get_int_enum_int_ft(field)->size, value),
- "Value is out of bounds: value=%" PRIu64 ", %![field-]+f",
- value, field);
- integer->payload.unsignd = value;
- bt_field_set(field, true);
- return 0;
+ struct bt_field_real *real_field = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field");
+ return real_field->value;
}
-int bt_field_floating_point_get_value(struct bt_field *field,
- double *value)
+void bt_field_real_set_value(struct bt_field *field, double value)
{
- struct bt_field_floating_point *floating_point = (void *) field;
+ struct bt_field_real *real_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field");
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_REAL, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
+ BT_ASSERT_PRE(
+ !((struct bt_field_type_real *) field->type)->is_single_precision ||
+ (double) (float) value == value,
+ "Invalid value for a single-precision real number: value=%f, "
+ "%![ft-]+F", value, field->type);
+ real_field->value = value;
+ bt_field_set_single(field, true);
+}
+
+int bt_field_unsigned_enumeration_get_mapping_labels(struct bt_field *field,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count)
+{
+ struct bt_field_integer *int_field = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_FLOAT, "Field");
- *value = floating_point->payload;
- return 0;
+ BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION, "Field");
+ return bt_field_type_unsigned_enumeration_get_mapping_labels_by_value(
+ field->type, int_field->value.u, label_array, count);
}
-int bt_field_floating_point_set_value(struct bt_field *field,
- double value)
+int bt_field_signed_enumeration_get_mapping_labels(struct bt_field *field,
+ bt_field_type_enumeration_mapping_label_array *label_array,
+ uint64_t *count)
{
- struct bt_field_floating_point *floating_point = (void *) field;
+ struct bt_field_integer *int_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
- BT_ASSERT_PRE_FIELD_HOT(field, "Floating point number field");
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
+ BT_ASSERT_PRE_NON_NULL(label_array, "Count (output)");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_FLOAT, "Field");
- floating_point->payload = value;
- bt_field_set(field, true);
- return 0;
+ BT_FIELD_TYPE_ID_SIGNED_ENUMERATION, "Field");
+ return bt_field_type_signed_enumeration_get_mapping_labels_by_value(
+ field->type, int_field->value.i, label_array, count);
}
const char *bt_field_string_get_value(struct bt_field *field)
{
- struct bt_field_string *string = (void *) field;
+ struct bt_field_string *string_field = (void *) field;
+
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING,
+ "Field");
+ return (const char *) string_field->buf->data;
+}
+
+uint64_t bt_field_string_get_length(struct bt_field *field)
+{
+ struct bt_field_string *string_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "String field");
- BT_ASSERT_PRE_FIELD_IS_SET(field, "String field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_STRING, "Field");
- return (const char *) string->buf->data;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_SET(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING,
+ "Field");
+ return string_field->length;
}
int bt_field_string_set_value(struct bt_field *field, const char *value)
{
- BT_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_HOT(field, "String field");
- BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
- BT_FIELD_TYPE_ID_STRING, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING,
+ "Field");
bt_field_string_clear(field);
- return bt_field_string_append_len(field,
- value, strlen(value));
+ return bt_field_string_append_with_length(field, value,
+ (uint64_t) strlen(value));
}
int bt_field_string_append(struct bt_field *field, const char *value)
{
- BT_ASSERT_PRE_NON_NULL(value, "Value");
- return bt_field_string_append_len(field, value,
- strlen(value));
+ return bt_field_string_append_with_length(field, value,
+ (uint64_t) strlen(value));
}
-int bt_field_string_append_len(struct bt_field *field,
- const char *value, unsigned int length)
+int bt_field_string_append_with_length(struct bt_field *field,
+ const char *value, uint64_t length)
{
struct bt_field_string *string_field = (void *) field;
char *data;
- size_t new_size;
+ uint64_t new_length;
- BT_ASSERT_PRE_NON_NULL(field, "String field");
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
BT_ASSERT_PRE_NON_NULL(value, "Value");
- BT_ASSERT_PRE_FIELD_HOT(field, "String field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
BT_FIELD_TYPE_ID_STRING, "Field");
/* Make sure no null bytes are appended */
BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
"String value to append contains a null character: "
- "partial-value=\"%.32s\", length=%u", value, length);
+ "partial-value=\"%.32s\", length=%" PRIu64, value, length);
- new_size = string_field->size + length;
+ new_length = length + string_field->length;
- if (unlikely(new_size + 1 > string_field->buf->len)) {
- g_array_set_size(string_field->buf, new_size + 1);
+ if (unlikely(new_length + 1 > string_field->buf->len)) {
+ g_array_set_size(string_field->buf, new_length + 1);
}
data = string_field->buf->data;
- memcpy(data + string_field->size, value, length);
- ((char *) string_field->buf->data)[new_size] = '\0';
- string_field->size = new_size;
- bt_field_set(field, true);
+ memcpy(data + string_field->length, value, length);
+ ((char *) string_field->buf->data)[new_length] = '\0';
+ string_field->length = new_length;
+ bt_field_set_single(field, true);
return 0;
}
{
struct bt_field_string *string_field = (void *) field;
- BT_ASSERT_PRE_NON_NULL(field, "String field");
- BT_ASSERT_PRE_FIELD_HOT(field, "String field");
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
BT_FIELD_TYPE_ID_STRING, "Field");
- string_field->size = 0;
- bt_field_set(field, true);
+ string_field->length = 0;
+ bt_field_set_single(field, true);
return 0;
}
-static inline
-void bt_field_finalize(struct bt_field *field)
+uint64_t bt_field_array_get_length(struct bt_field *field)
{
- BT_ASSERT(field);
- BT_LOGD_STR("Putting field's type.");
- bt_put(field->type);
-}
+ struct bt_field_array *array_field = (void *) field;
-static
-void bt_field_integer_destroy(struct bt_field *field)
-{
- BT_ASSERT(field);
- BT_LOGD("Destroying integer field object: addr=%p", field);
- bt_field_finalize(field);
- g_free(field);
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field");
+ return array_field->length;
}
-static
-void bt_field_floating_point_destroy(struct bt_field *field)
+int bt_field_dynamic_array_set_length(struct bt_field *field,
+ uint64_t length)
{
- BT_ASSERT(field);
- BT_LOGD("Destroying floating point field object: addr=%p", field);
- bt_field_finalize(field);
- g_free(field);
-}
+ int ret = 0;
+ struct bt_field_array *array_field = (void *) field;
-static
-void bt_field_enumeration_destroy(struct bt_field *field)
-{
- BT_LOGD("Destroying enumeration field object: addr=%p", field);
- bt_field_finalize((void *) field);
- g_free(field);
-}
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_DYNAMIC_ARRAY, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
-static
-void bt_field_structure_destroy_recursive(struct bt_field *field)
-{
- struct bt_field_structure *structure = (void *) field;
+ if (unlikely(length > array_field->fields->len)) {
+ /* Make more room */
+ struct bt_field_type_array *array_ft;
+ uint64_t cur_len = array_field->fields->len;
+ uint64_t i;
- BT_ASSERT(field);
- BT_LOGD("Destroying structure field object: addr=%p", field);
- bt_field_finalize(field);
-
- if (structure->fields) {
- g_ptr_array_free(structure->fields, TRUE);
- }
-
- g_free(field);
-}
-
-static
-void bt_field_variant_destroy_recursive(struct bt_field *field)
-{
- struct bt_field_variant *variant = (void *) field;
-
- BT_ASSERT(field);
- BT_LOGD("Destroying variant field object: addr=%p", field);
- bt_field_finalize(field);
-
- if (variant->fields) {
- g_ptr_array_free(variant->fields, TRUE);
- }
-
- g_free(field);
-}
-
-static
-void bt_field_array_destroy_recursive(struct bt_field *field)
-{
- struct bt_field_array *array = (void *) field;
-
- BT_ASSERT(field);
- BT_LOGD("Destroying array field object: addr=%p", field);
- bt_field_finalize(field);
-
- if (array->elements) {
- g_ptr_array_free(array->elements, TRUE);
- }
-
- g_free(field);
-}
-
-static
-void bt_field_sequence_destroy_recursive(struct bt_field *field)
-{
- struct bt_field_sequence *sequence = (void *) field;
-
- BT_ASSERT(field);
- BT_LOGD("Destroying sequence field object: addr=%p", field);
- bt_field_finalize(field);
-
- if (sequence->elements) {
- g_ptr_array_free(sequence->elements, TRUE);
- }
- g_free(field);
-}
-
-static
-void bt_field_string_destroy(struct bt_field *field)
-{
- struct bt_field_string *string = (void *) field;
-
- BT_LOGD("Destroying string field object: addr=%p", field);
- BT_ASSERT(field);
- bt_field_finalize(field);
-
- if (string->buf) {
- g_array_free(string->buf, TRUE);
- }
+ g_ptr_array_set_size(array_field->fields, length);
+ array_ft = (void *) field->type;
- g_free(field);
-}
-
-BT_HIDDEN
-void bt_field_destroy_recursive(struct bt_field *field)
-{
- if (!field) {
- return;
- }
-
- BT_ASSERT(bt_field_type_has_known_id((void *) field->type));
- field_destroy_funcs[field->type->id](field);
-}
-
-static inline
-void bt_field_initialize(struct bt_field *field,
- struct bt_field_type *ft,
- struct bt_field_methods *methods)
-{
- BT_ASSERT(field);
- BT_ASSERT(ft);
- bt_object_init_unique(&field->base);
- field->methods = methods;
- field->type = bt_get(ft);
-}
-
-static
-struct bt_field *bt_field_integer_create(struct bt_field_type *type)
-{
- struct bt_field_integer *integer =
- g_new0(struct bt_field_integer, 1);
-
- BT_LOGD("Creating integer field object: ft-addr=%p", type);
-
- if (integer) {
- bt_field_initialize((void *) integer, (void *) type,
- &bt_field_integer_methods);
- BT_LOGD("Created 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_field *bt_field_enumeration_create(struct bt_field_type *type)
-{
- struct bt_field_enumeration *enumeration = g_new0(
- struct bt_field_enumeration, 1);
-
- BT_LOGD("Creating enumeration field object: ft-addr=%p", type);
-
- if (enumeration) {
- bt_field_initialize((void *) enumeration,
- (void *) type, &bt_field_enumeration_methods);
- BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p",
- enumeration, type);
- } else {
- BT_LOGE_STR("Failed to allocate one enumeration field.");
- }
-
- return (void *) enumeration;
-}
+ for (i = cur_len; i < array_field->fields->len; i++) {
+ struct bt_field *elem_field = bt_field_create(
+ array_ft->element_ft);
-static
-struct bt_field *bt_field_floating_point_create(struct bt_field_type *type)
-{
- struct bt_field_floating_point *floating_point;
-
- BT_LOGD("Creating floating point number field object: ft-addr=%p", type);
- floating_point = g_new0(struct bt_field_floating_point, 1);
-
- if (floating_point) {
- bt_field_initialize((void *) floating_point,
- (void *) type, &bt_field_floating_point_methods);
- BT_LOGD("Created 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 inline
-int bt_field_structure_initialize(struct bt_field *field,
- struct bt_field_type *type,
- struct bt_field_methods *methods,
- bt_field_create_func field_create_func,
- GDestroyNotify field_release_func)
-{
- int ret = 0;
- struct bt_field_type_structure *structure_type = (void *) type;
- struct bt_field_structure *structure = (void *) field;
- size_t i;
-
- BT_LOGD("Initializing structure field object: ft-addr=%p", type);
- bt_field_initialize(field, type, methods);
- structure->fields = g_ptr_array_new_with_free_func(field_release_func);
- g_ptr_array_set_size(structure->fields, structure_type->fields->len);
+ if (!elem_field) {
+ BT_LIB_LOGE("Cannot create element field for "
+ "dynamic array field: "
+ "index=%" PRIu64 ", "
+ "%![array-field-]+f", i, field);
+ ret = -1;
+ goto end;
+ }
- /* Create all fields contained in the structure field. */
- for (i = 0; i < structure_type->fields->len; i++) {
- struct bt_field *field;
- struct bt_field_type_structure_field *struct_field =
- BT_FIELD_TYPE_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;
+ BT_ASSERT(!array_field->fields->pdata[i]);
+ array_field->fields->pdata[i] = elem_field;
}
-
- g_ptr_array_index(structure->fields, i) = field;
}
- BT_LOGD("Initialized structure field object: addr=%p, ft-addr=%p",
- field, type);
+ array_field->length = length;
end:
return ret;
}
-static
-struct bt_field *bt_field_structure_create(struct bt_field_type *type)
-{
- struct bt_field_structure *structure = g_new0(
- struct bt_field_structure, 1);
- int iret;
-
- BT_LOGD("Creating structure field object: ft-addr=%p", type);
-
- if (!structure) {
- BT_LOGE_STR("Failed to allocate one structure field.");
- goto end;
- }
-
- iret = bt_field_structure_initialize((void *) structure,
- (void *) type, &bt_field_structure_methods,
- (bt_field_create_func) bt_field_create_recursive,
- (GDestroyNotify) bt_field_destroy_recursive);
- if (iret) {
- BT_PUT(structure);
- goto end;
- }
-
- BT_LOGD("Created structure field object: addr=%p, ft-addr=%p",
- structure, type);
-
-end:
- return (void *) structure;
-}
-
-static inline
-int bt_field_variant_initialize(struct bt_field *field,
- struct bt_field_type *type,
- struct bt_field_methods *methods,
- bt_field_create_func field_create_func,
- GDestroyNotify field_release_func)
+struct bt_field *bt_field_array_borrow_element_field_by_index(
+ struct bt_field *field, uint64_t index)
{
- int ret = 0;
- struct bt_field_type_variant *variant_type = (void *) type;
- struct bt_field_variant *variant = (void *) field;
- size_t i;
-
- BT_LOGD("Initializing variant field object: ft-addr=%p", type);
- bt_field_initialize(field, type, methods);
- ret = bt_field_type_variant_update_choices(type);
- if (ret) {
- BT_LOGE("Cannot update 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_field *field;
- struct bt_field_type_variant_choice *var_choice =
- BT_FIELD_TYPE_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 variant field object: addr=%p, ft-addr=%p",
- field, type);
+ struct bt_field_array *array_field = (void *) field;
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_IS_ARRAY(field, "Field");
+ BT_ASSERT_PRE_VALID_INDEX(index, array_field->length);
+ return array_field->fields->pdata[index];
}
-static inline
-int bt_field_string_initialize(struct bt_field *field,
- struct bt_field_type *type,
- struct bt_field_methods *methods)
+struct bt_field *bt_field_structure_borrow_member_field_by_index(
+ struct bt_field *field, uint64_t index)
{
- int ret = 0;
- struct bt_field_string *string = (void *) field;
-
- BT_LOGD("Initializing string field object: ft-addr=%p", type);
- bt_field_initialize(field, type, 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 string field object: addr=%p, ft-addr=%p",
- field, type);
+ struct bt_field_structure *struct_field = (void *) field;
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_STRUCTURE, "Field");
+ BT_ASSERT_PRE_VALID_INDEX(index, struct_field->fields->len);
+ return struct_field->fields->pdata[index];
}
-static
-struct bt_field *bt_field_variant_create(struct bt_field_type *type)
+struct bt_field *bt_field_structure_borrow_member_field_by_name(
+ struct bt_field *field, const char *name)
{
- struct bt_field_variant *variant = g_new0(
- struct bt_field_variant, 1);
- int iret;
+ struct bt_field *ret_field = NULL;
+ struct bt_field_type_structure *struct_ft;
+ struct bt_field_structure *struct_field = (void *) field;
+ gpointer orig_key;
+ gpointer index;
- BT_LOGD("Creating variant field object: ft-addr=%p", type);
-
- if (!variant) {
- BT_LOGE_STR("Failed to allocate one variant field.");
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_NON_NULL(name, "Field name");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_STRUCTURE, "Field");
+ struct_ft = (void *) field->type;
- iret = bt_field_variant_initialize((void *) variant,
- (void *) type, &bt_field_variant_methods,
- (bt_field_create_func) bt_field_create_recursive,
- (GDestroyNotify) bt_field_destroy_recursive);
- if (iret) {
- BT_PUT(variant);
+ if (!g_hash_table_lookup_extended(struct_ft->common.name_to_index, name,
+ &orig_key, &index)) {
goto end;
}
- BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
- variant, type);
+ ret_field = struct_field->fields->pdata[GPOINTER_TO_UINT(index)];
+ BT_ASSERT(ret_field);
end:
- return (void *) variant;
+ return ret_field;
}
-static inline
-int bt_field_array_initialize(struct bt_field *field,
- struct bt_field_type *type,
- struct bt_field_methods *methods,
- bt_field_create_func field_create_func,
- GDestroyNotify field_destroy_func)
+struct bt_field *bt_field_variant_borrow_selected_option_field(
+ struct bt_field *field)
{
- struct bt_field_type_array *array_type = (void *) type;
- struct bt_field_array *array = (void *) field;
- unsigned int array_length;
- int ret = 0;
- uint64_t i;
-
- BT_LOGD("Initializing array field object: ft-addr=%p", type);
- BT_ASSERT(type);
- bt_field_initialize(field, type, methods);
- array_length = array_type->length;
- array->elements = g_ptr_array_sized_new(array_length);
- if (!array->elements) {
- ret = -1;
- goto end;
- }
+ struct bt_field_variant *var_field = (void *) field;
- 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 array field object: addr=%p, ft-addr=%p",
- field, type);
-
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_ASSERT_PRE(var_field->selected_field,
+ "Variant field has no selected field: %!+f", field);
+ return var_field->selected_field;
}
-static
-struct bt_field *bt_field_array_create(struct bt_field_type *type)
+int bt_field_variant_select_option_field(struct bt_field *field,
+ uint64_t index)
{
- struct bt_field_array *array =
- g_new0(struct bt_field_array, 1);
- int ret;
+ struct bt_field_variant *var_field = (void *) field;
- BT_LOGD("Creating array field object: ft-addr=%p", type);
- BT_ASSERT(type);
-
- if (!array) {
- BT_LOGE_STR("Failed to allocate one array field.");
- goto end;
- }
-
- ret = bt_field_array_initialize((void *) array,
- (void *) type, &bt_field_array_methods,
- (bt_field_create_func) bt_field_create_recursive,
- (GDestroyNotify) bt_field_destroy_recursive);
- if (ret) {
- BT_PUT(array);
- goto end;
- }
-
- BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
- array, type);
-
-end:
- return (void *) array;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_ASSERT_PRE_FIELD_HOT(field, "Field");
+ BT_ASSERT_PRE_VALID_INDEX(index, var_field->fields->len);
+ var_field->selected_field = var_field->fields->pdata[index];
+ var_field->selected_index = index;
+ return 0;
}
-static inline
-int bt_field_sequence_initialize(struct bt_field *field,
- struct bt_field_type *type,
- struct bt_field_methods *methods,
- GDestroyNotify field_destroy_func)
+uint64_t bt_field_variant_get_selected_option_field_index(
+ struct bt_field *field)
{
- struct bt_field_sequence *sequence = (void *) field;
- int ret = 0;
-
- BT_LOGD("Initializing sequence field object: ft-addr=%p", type);
- BT_ASSERT(type);
- bt_field_initialize(field, type, methods);
- sequence->elements = g_ptr_array_new();
- if (!sequence->elements) {
- ret = -1;
- goto end;
- }
+ struct bt_field_variant *var_field = (void *) field;
- g_ptr_array_set_free_func(sequence->elements, field_destroy_func);
- BT_LOGD("Initialized sequence field object: addr=%p, ft-addr=%p",
- field, type);
-
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(field, "Field");
+ BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field,
+ BT_FIELD_TYPE_ID_VARIANT, "Field");
+ BT_ASSERT_PRE(var_field->selected_field,
+ "Variant field has no selected field: %!+f", field);
+ return var_field->selected_index;
}
-static
-struct bt_field *bt_field_sequence_create(struct bt_field_type *type)
+static inline
+void bt_field_finalize(struct bt_field *field)
{
- struct bt_field_sequence *sequence =
- g_new0(struct bt_field_sequence, 1);
- int ret;
-
- BT_LOGD("Creating sequence field object: ft-addr=%p", type);
- BT_ASSERT(type);
-
- if (!sequence) {
- BT_LOGE_STR("Failed to allocate one sequence field.");
- goto end;
- }
-
- ret = bt_field_sequence_initialize((void *) sequence,
- (void *) type, &bt_field_sequence_methods,
- (GDestroyNotify) bt_field_destroy_recursive);
- if (ret) {
- BT_PUT(sequence);
- goto end;
- }
-
- BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
- sequence, type);
-
-end:
- return (void *) sequence;
+ BT_ASSERT(field);
+ BT_LOGD_STR("Putting field's type.");
+ bt_put(field->type);
}
static
-struct bt_field *bt_field_string_create(struct bt_field_type *type)
+void destroy_integer_field(struct bt_field *field)
{
- struct bt_field_string *string = g_new0(
- struct bt_field_string, 1);
-
- BT_LOGD("Creating string field object: ft-addr=%p", type);
-
- if (string) {
- bt_field_string_initialize((void *) string,
- (void *) type, &bt_field_string_methods);
- BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
- string, type);
- } else {
- BT_LOGE_STR("Failed to allocate one string field.");
- }
-
- return (void *) string;
+ BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying integer field object: %!+f", field);
+ bt_field_finalize(field);
+ g_free(field);
}
static
-int bt_field_generic_validate(struct bt_field *field)
+void destroy_real_field(struct bt_field *field)
{
- return (field && field->payload_set) ? 0 : -1;
+ BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying real field object: %!+f", field);
+ bt_field_finalize(field);
+ g_free(field);
}
static
-int bt_field_structure_validate_recursive(struct bt_field *field)
+void destroy_structure_field(struct bt_field *field)
{
- int64_t i;
- int ret = 0;
- struct bt_field_structure *structure = (void *) field;
+ struct bt_field_structure *struct_field = (void *) field;
BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying structure field object: %!+f", field);
+ bt_field_finalize(field);
- for (i = 0; i < structure->fields->len; i++) {
- ret = bt_field_validate_recursive(
- (void *) structure->fields->pdata[i]);
-
- if (ret) {
- int this_ret;
- const char *name;
-
- this_ret = bt_field_type_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-]+f, field-name=\"%s\", "
- "index=%" PRId64 ", %![field-]+f",
- field, name, i, structure->fields->pdata[i]);
- goto end;
- }
+ if (struct_field->fields) {
+ g_ptr_array_free(struct_field->fields, TRUE);
}
-end:
- return ret;
+ g_free(field);
}
static
-int bt_field_variant_validate_recursive(struct bt_field *field)
+void destroy_variant_field(struct bt_field *field)
{
- int ret = 0;
- struct bt_field_variant *variant = (void *) field;
+ struct bt_field_variant *var_field = (void *) field;
BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying variant field object: %!+f", field);
+ bt_field_finalize(field);
- if (!variant->current_field) {
- ret = -1;
- goto end;
+ if (var_field->fields) {
+ g_ptr_array_free(var_field->fields, TRUE);
}
- ret = bt_field_validate_recursive(variant->current_field);
-
-end:
- return ret;
+ g_free(field);
}
static
-int bt_field_array_validate_recursive(struct bt_field *field)
+void destroy_array_field(struct bt_field *field)
{
- int64_t i;
- int ret = 0;
- struct bt_field_array *array = (void *) field;
+ struct bt_field_array *array_field = (void *) field;
BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying array field object: %!+f", field);
+ bt_field_finalize(field);
- for (i = 0; i < array->elements->len; i++) {
- ret = bt_field_validate_recursive((void *) array->elements->pdata[i]);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid array field's element field: "
- "%![array-field-]+f, " PRId64 ", "
- "%![elem-field-]+f",
- field, i, array->elements->pdata[i]);
- goto end;
- }
+ if (array_field->fields) {
+ g_ptr_array_free(array_field->fields, TRUE);
}
-end:
- return ret;
+ g_free(field);
}
static
-int bt_field_sequence_validate_recursive(struct bt_field *field)
+void destroy_string_field(struct bt_field *field)
{
- size_t i;
- int ret = 0;
- struct bt_field_sequence *sequence = (void *) field;
+ struct bt_field_string *string_field = (void *) field;
BT_ASSERT(field);
+ BT_LIB_LOGD("Destroying string field object: %!+f", field);
+ bt_field_finalize(field);
- for (i = 0; i < sequence->elements->len; i++) {
- ret = bt_field_validate_recursive(
- (void *) sequence->elements->pdata[i]);
- if (ret) {
- BT_ASSERT_PRE_MSG("Invalid sequence field's element field: "
- "%![seq-field-]+f, " PRId64 ", "
- "%![elem-field-]+f",
- field, i, sequence->elements->pdata[i]);
- goto end;
- }
+ if (string_field->buf) {
+ g_array_free(string_field->buf, TRUE);
}
-end:
- return ret;
+
+ g_free(field);
}
-static
-void bt_field_generic_reset(struct bt_field *field)
+BT_HIDDEN
+void bt_field_destroy(struct bt_field *field)
{
BT_ASSERT(field);
- field->payload_set = false;
+ BT_ASSERT(bt_field_type_has_known_id(field->type));
+ field_destroy_funcs[field->type->id](field);
}
static
-void bt_field_structure_reset_recursive(struct bt_field *field)
+void reset_single_field(struct bt_field *field)
{
- int64_t i;
- struct bt_field_structure *structure = (void *) field;
-
BT_ASSERT(field);
-
- for (i = 0; i < structure->fields->len; i++) {
- struct bt_field *member = structure->fields->pdata[i];
-
- if (!member) {
- /*
- * Structure members are lazily initialized;
- * skip if this member has not been allocated
- * yet.
- */
- continue;
- }
-
- bt_field_reset_recursive(member);
- }
+ field->is_set = false;
}
static
-void bt_field_variant_reset_recursive(struct bt_field *field)
+void reset_structure_field(struct bt_field *field)
{
- struct bt_field_variant *variant = (void *) field;
+ uint64_t i;
+ struct bt_field_structure *struct_field = (void *) field;
BT_ASSERT(field);
- variant->current_field = NULL;
+
+ for (i = 0; i < struct_field->fields->len; i++) {
+ bt_field_reset(struct_field->fields->pdata[i]);
+ }
}
static
-void bt_field_array_reset_recursive(struct bt_field *field)
+void reset_variant_field(struct bt_field *field)
{
- size_t i;
- struct bt_field_array *array = (void *) field;
+ uint64_t i;
+ struct bt_field_variant *var_field = (void *) field;
BT_ASSERT(field);
- for (i = 0; i < array->elements->len; i++) {
- struct bt_field *member = array->elements->pdata[i];
-
- if (!member) {
- /*
- * Array elements are lazily initialized; skip
- * if this member has not been allocated yet.
- */
- continue;
- }
-
- bt_field_reset_recursive(member);
+ for (i = 0; i < var_field->fields->len; i++) {
+ bt_field_reset(var_field->fields->pdata[i]);
}
}
static
-void bt_field_sequence_reset_recursive(struct bt_field *field)
+void reset_array_field(struct bt_field *field)
{
- struct bt_field_sequence *sequence = (void *) field;
uint64_t i;
+ struct bt_field_array *array_field = (void *) field;
BT_ASSERT(field);
- for (i = 0; i < sequence->elements->len; i++) {
- if (sequence->elements->pdata[i]) {
- bt_field_reset_recursive(
- sequence->elements->pdata[i]);
- }
+ for (i = 0; i < array_field->fields->len; i++) {
+ bt_field_reset(array_field->fields->pdata[i]);
}
-
- sequence->length = 0;
}
static
-void bt_field_generic_set_is_frozen(struct bt_field *field,
- bool is_frozen)
+void set_single_field_is_frozen(struct bt_field *field, bool is_frozen)
{
field->frozen = is_frozen;
}
static
-void bt_field_structure_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen)
+void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen)
{
uint64_t i;
- struct bt_field_structure *structure_field = (void *) field;
+ struct bt_field_structure *struct_field = (void *) field;
- BT_LOGD("Freezing structure field object: addr=%p", field);
+ BT_LIB_LOGD("Setting structure field's frozen state: "
+ "%![field-]+f, is-frozen=%d", field, is_frozen);
- for (i = 0; i < structure_field->fields->len; i++) {
- struct bt_field *struct_field =
- g_ptr_array_index(structure_field->fields, i);
+ for (i = 0; i < struct_field->fields->len; i++) {
+ struct bt_field *member_field = struct_field->fields->pdata[i];
- BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
- struct_field, i);
- bt_field_set_is_frozen_recursive(struct_field,
- is_frozen);
+ BT_LIB_LOGD("Setting structure field's member field's "
+ "frozen state: %![field-]+f, index=%" PRIu64,
+ member_field, i);
+ bt_field_set_is_frozen(member_field, is_frozen);
}
- bt_field_generic_set_is_frozen(field, is_frozen);
+ set_single_field_is_frozen(field, is_frozen);
}
static
-void bt_field_variant_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen)
+void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen)
{
uint64_t i;
- struct bt_field_variant *variant_field = (void *) field;
+ struct bt_field_variant *var_field = (void *) field;
- BT_LOGD("Freezing variant field object: addr=%p", field);
+ BT_LIB_LOGD("Setting variant field's frozen state: "
+ "%![field-]+f, is-frozen=%d", field, is_frozen);
- for (i = 0; i < variant_field->fields->len; i++) {
- struct bt_field *var_field =
- g_ptr_array_index(variant_field->fields, i);
+ for (i = 0; i < var_field->fields->len; i++) {
+ struct bt_field *option_field = var_field->fields->pdata[i];
- BT_LOGD("Freezing variant field's field: field-addr=%p, index=%" PRId64,
- var_field, i);
- bt_field_set_is_frozen_recursive(var_field, is_frozen);
+ BT_LIB_LOGD("Setting variant field's option field's "
+ "frozen state: %![field-]+f, index=%" PRIu64,
+ option_field, i);
+ bt_field_set_is_frozen(option_field, is_frozen);
}
- bt_field_generic_set_is_frozen(field, is_frozen);
+ set_single_field_is_frozen(field, is_frozen);
}
static
-void bt_field_array_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen)
+void set_array_field_is_frozen(struct bt_field *field, bool is_frozen)
{
- int64_t i;
+ uint64_t i;
struct bt_field_array *array_field = (void *) field;
- BT_LOGD("Freezing array field object: addr=%p", field);
+ BT_LIB_LOGD("Setting array field's frozen state: "
+ "%![field-]+f, is-frozen=%d", field, is_frozen);
- for (i = 0; i < array_field->elements->len; i++) {
- struct bt_field *elem_field =
- g_ptr_array_index(array_field->elements, i);
+ for (i = 0; i < array_field->fields->len; i++) {
+ struct bt_field *elem_field = array_field->fields->pdata[i];
- BT_LOGD("Freezing array field object's element field: "
- "element-field-addr=%p, index=%" PRId64,
+ BT_LIB_LOGD("Setting array field's element field's "
+ "frozen state: %![field-]+f, index=%" PRIu64,
elem_field, i);
- bt_field_set_is_frozen_recursive(elem_field, is_frozen);
+ bt_field_set_is_frozen(elem_field, is_frozen);
}
- bt_field_generic_set_is_frozen(field, is_frozen);
-}
-
-static
-void bt_field_sequence_set_is_frozen_recursive(
- struct bt_field *field, bool is_frozen)
-{
- int64_t i;
- struct bt_field_sequence *sequence_field = (void *) field;
-
- BT_LOGD("Freezing sequence field object: addr=%p", field);
-
- for (i = 0; i < sequence_field->length; i++) {
- struct bt_field *elem_field =
- g_ptr_array_index(sequence_field->elements, i);
-
- BT_LOGD("Freezing sequence field object's element field: "
- "element-field-addr=%p, index=%" PRId64,
- elem_field, i);
- bt_field_set_is_frozen_recursive(elem_field, is_frozen);
- }
-
- bt_field_generic_set_is_frozen(field, is_frozen);
+ set_single_field_is_frozen(field, is_frozen);
}
BT_HIDDEN
-void _bt_field_set_is_frozen_recursive(struct bt_field *field,
+void _bt_field_set_is_frozen(struct bt_field *field,
bool is_frozen)
{
- if (!field) {
- goto end;
- }
-
- BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d",
+ BT_ASSERT(field);
+ BT_LIB_LOGD("Setting field object's frozen state: %!+f, is-frozen=%d",
field, is_frozen);
- BT_ASSERT(bt_field_type_has_known_id(field->type));
BT_ASSERT(field->methods->set_is_frozen);
field->methods->set_is_frozen(field, is_frozen);
-
-end:
- return;
}
static
-bt_bool bt_field_generic_is_set(struct bt_field *field)
+bool single_field_is_set(struct bt_field *field)
{
- return field && field->payload_set;
+ BT_ASSERT(field);
+ return field->is_set;
}
static
-bt_bool bt_field_structure_is_set_recursive(
- struct bt_field *field)
+bool structure_field_is_set(struct bt_field *field)
{
- bt_bool is_set = BT_FALSE;
- size_t i;
- struct bt_field_structure *structure = (void *) field;
+ bool is_set = true;
+ uint64_t i;
+ struct bt_field_structure *struct_field = (void *) field;
BT_ASSERT(field);
- for (i = 0; i < structure->fields->len; i++) {
- is_set = bt_field_is_set_recursive(
- structure->fields->pdata[i]);
+ for (i = 0; i < struct_field->fields->len; i++) {
+ is_set = bt_field_is_set(struct_field->fields->pdata[i]);
if (!is_set) {
goto end;
}
}
static
-bt_bool bt_field_variant_is_set_recursive(struct bt_field *field)
-{
- struct bt_field_variant *variant = (void *) field;
- bt_bool is_set = BT_FALSE;
-
- BT_ASSERT(field);
-
- if (variant->current_field) {
- is_set = bt_field_is_set_recursive(
- variant->current_field);
- }
-
- return is_set;
-}
-
-static
-bt_bool bt_field_array_is_set_recursive(struct bt_field *field)
+bool variant_field_is_set(struct bt_field *field)
{
- size_t i;
- bt_bool is_set = BT_FALSE;
- struct bt_field_array *array = (void *) field;
+ struct bt_field_variant *var_field = (void *) field;
+ bool is_set = false;
BT_ASSERT(field);
- for (i = 0; i < array->elements->len; i++) {
- is_set = bt_field_is_set_recursive(array->elements->pdata[i]);
- if (!is_set) {
- goto end;
- }
+ if (var_field->selected_field) {
+ is_set = bt_field_is_set(var_field->selected_field);
}
-end:
return is_set;
}
static
-bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field)
+bool array_field_is_set(struct bt_field *field)
{
- size_t i;
- bt_bool is_set = BT_FALSE;
- struct bt_field_sequence *sequence = (void *) field;
+ bool is_set = true;
+ uint64_t i;
+ struct bt_field_array *array_field = (void *) field;
BT_ASSERT(field);
- if (!sequence->elements) {
- goto end;
- }
-
- for (i = 0; i < sequence->elements->len; i++) {
- is_set = bt_field_is_set_recursive(
- sequence->elements->pdata[i]);
+ for (i = 0; i < array_field->length; i++) {
+ is_set = bt_field_is_set(array_field->fields->pdata[i]);
if (!is_set) {
goto end;
}
#include <babeltrace/lib-logging-internal.h>
#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/ctf-ir/packet-context-field.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
struct bt_field_wrapper *field_wrapper = (void *) context_field;
BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet context field");
- BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
- "Packet context field's field object");
- return (void *) field_wrapper->field;
+ return field_wrapper->field;
}
void bt_packet_context_field_release(struct bt_packet_context_field *context_field)
* Do not recycle because the pool could be destroyed at this
* point. This function is only called when there's an error
* anyway because the goal of a packet context field wrapper is
- * to eventually move it to a packet with bt_packet_move_context()
- * after creating it.
+ * to eventually move it to a packet with
+ * bt_packet_move_context() after creating it.
*/
bt_field_wrapper_destroy(field_wrapper);
}
+
+struct bt_packet_context_field *bt_packet_context_field_create(
+ struct bt_stream_class *stream_class)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->frozen,
+ "Stream class is not part of a trace: %!+S", stream_class);
+ BT_ASSERT_PRE(stream_class->packet_context_ft,
+ "Stream class has no packet context field type: %!+S",
+ stream_class);
+ field_wrapper = bt_field_wrapper_create(
+ &stream_class->packet_context_field_pool,
+ (void *) stream_class->packet_context_ft);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
+ "%![sc-]+S", stream_class);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ bt_stream_class_freeze(stream_class);
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
#include <babeltrace/lib-logging-internal.h>
#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/trace-internal.h>
#include <babeltrace/ctf-ir/packet-header-field.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
{
struct bt_field_wrapper *field_wrapper = (void *) header_field;
- BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
- BT_ASSERT_PRE_NON_NULL(field_wrapper->field,
- "Event header field's field object");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field");
return (void *) field_wrapper->field;
}
{
struct bt_field_wrapper *field_wrapper = (void *) header_field;
- BT_ASSERT_PRE_NON_NULL(field_wrapper, "Event header field");
+ BT_ASSERT_PRE_NON_NULL(field_wrapper, "Packet header field");
/*
* Do not recycle because the pool could be destroyed at this
*/
bt_field_wrapper_destroy(field_wrapper);
}
+
+struct bt_packet_header_field *bt_packet_header_field_create(
+ struct bt_trace *trace)
+{
+ struct bt_field_wrapper *field_wrapper;
+
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE(trace->packet_header_ft,
+ "Trace has no packet header field type: %!+t", trace);
+ field_wrapper = bt_field_wrapper_create(
+ &trace->packet_header_field_pool,
+ (void *) trace->packet_header_ft);
+ if (!field_wrapper) {
+ BT_LIB_LOGE("Cannot allocate one packet header field from trace: "
+ "%![trace-]+t", trace);
+ goto error;
+ }
+
+ BT_ASSERT(field_wrapper->field);
+ bt_trace_freeze(trace);
+ goto end;
+
+error:
+ if (field_wrapper) {
+ bt_field_wrapper_destroy(field_wrapper);
+ field_wrapper = NULL;
+ }
+
+end:
+ return (void *) field_wrapper;
+}
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace/ctf-ir/stream.h>
#include <babeltrace/ctf-ir/stream-internal.h>
+#include <babeltrace/ctf-ir/clock-value-internal.h>
#include <babeltrace/ctf-ir/trace-internal.h>
#include <babeltrace/object-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/assert-internal.h>
#include <inttypes.h>
+#define BT_ASSERT_PRE_PACKET_HOT(_packet) \
+ BT_ASSERT_PRE_HOT((_packet), "Packet", ": %!+a", (_packet))
+
struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
return packet->stream;
}
-struct bt_field *bt_packet_borrow_header(struct bt_packet *packet)
+struct bt_field *bt_packet_borrow_header_field(struct bt_packet *packet)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- return packet->header ? (void *) packet->header->field : NULL;
+ return packet->header_field ? packet->header_field->field : NULL;
}
-struct bt_field *bt_packet_borrow_context(struct bt_packet *packet)
+struct bt_field *bt_packet_borrow_context_field(struct bt_packet *packet)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- return packet->context ? (void *) packet->context->field : NULL;
+ return packet->context_field ? packet->context_field->field : NULL;
}
BT_HIDDEN
return;
}
- BT_LOGD("Setting packet's frozen state: addr=%p, frozen=%d",
- packet, is_frozen);
+ BT_LIB_LOGD("Setting packet's frozen state: %![packet-]+a, "
+ "is-frozen=%d", packet, is_frozen);
- if (packet->header) {
- BT_LOGD("Setting packet's header field's frozen state: "
- "frozen=%d", is_frozen);
- bt_field_set_is_frozen_recursive((void *) packet->header->field,
+ if (packet->header_field) {
+ BT_LOGD_STR("Setting packet's header field's frozen state.");
+ bt_field_set_is_frozen(packet->header_field->field,
is_frozen);
}
- if (packet->context) {
- BT_LOGD("Setting packet's context field's frozen state: "
- "frozen=%d", is_frozen);
- bt_field_set_is_frozen_recursive((void *) packet->context->field,
+ if (packet->context_field) {
+ BT_LOGD_STR("Setting packet's context field's frozen state.");
+ bt_field_set_is_frozen(packet->context_field->field,
is_frozen);
}
}
static inline
-void bt_packet_reset_avail(struct bt_packet *packet)
+void reset_counter_snapshots(struct bt_packet *packet)
{
- /* Previous packet */
- packet->prev_packet_info.avail =
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE;
- packet->prev_packet_info.discarded_event_counter.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- packet->prev_packet_info.seq_num.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- packet->prev_packet_info.default_end_cv.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
-
- /* Current packet */
- packet->discarded_event_counter.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- packet->seq_num.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
-
- /* Computed */
- packet->discarded_event_count.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- packet->discarded_packet_count.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
+ packet->discarded_event_counter_snapshot.base.avail =
+ BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
+ packet->packet_counter_snapshot.base.avail =
+ BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
}
static inline
-void bt_packet_reset(struct bt_packet *packet)
+void reset_packet(struct bt_packet *packet)
{
BT_ASSERT(packet);
+ BT_LIB_LOGD("Resetting packet: %!+a", packet);
bt_packet_set_is_frozen(packet, false);
- if (packet->header) {
- bt_field_set_is_frozen_recursive(
- (void *) packet->header->field, false);
- bt_field_reset_recursive((void *) packet->header->field);
+ if (packet->header_field) {
+ bt_field_set_is_frozen(packet->header_field->field, false);
+ bt_field_reset(packet->header_field->field);
}
- if (packet->context) {
- bt_field_set_is_frozen_recursive(
- (void *) packet->context->field, false);
- bt_field_reset_recursive((void *) packet->context->field);
+ if (packet->context_field) {
+ bt_field_set_is_frozen(packet->context_field->field, false);
+ bt_field_reset(packet->context_field->field);
}
- bt_clock_value_set_reset(&packet->begin_cv_set);
- bt_clock_value_set_reset(&packet->end_cv_set);
- bt_packet_reset_avail(packet);
- bt_packet_invalidate_properties(packet);
+ if (packet->default_beginning_cv) {
+ bt_clock_value_reset(packet->default_beginning_cv);
+ }
- if (packet->prev_packet_info.default_end_cv.cv) {
- bt_clock_value_recycle(packet->prev_packet_info.default_end_cv.cv);
- packet->prev_packet_info.default_end_cv.cv = NULL;
+ if (packet->default_end_cv) {
+ bt_clock_value_reset(packet->default_end_cv);
}
+
+ reset_counter_snapshots(packet);
}
static
-void bt_packet_header_field_recycle(struct bt_field_wrapper *header_field,
+void recycle_header_field(struct bt_field_wrapper *header_field,
struct bt_trace *trace)
{
BT_ASSERT(header_field);
}
static
-void bt_packet_context_field_recycle(struct bt_field_wrapper *context_field,
+void recycle_context_field(struct bt_field_wrapper *context_field,
struct bt_stream_class *stream_class)
{
BT_ASSERT(context_field);
*
* 4. Put our stream reference.
*/
- bt_packet_reset(packet);
+ reset_packet(packet);
stream = packet->stream;
BT_ASSERT(stream);
packet->stream = NULL;
BT_HIDDEN
void bt_packet_destroy(struct bt_packet *packet)
{
- BT_LOGD("Destroying packet: addr=%p", packet);
- BT_LOGD_STR("Destroying packet's header field.");
+ BT_LIB_LOGD("Destroying packet: %!+a", packet);
- if (packet->header) {
+ if (packet->header_field) {
if (packet->stream) {
BT_LOGD_STR("Recycling packet's header field.");
- bt_packet_header_field_recycle(packet->header,
- bt_stream_class_borrow_trace(
- bt_stream_borrow_class(packet->stream)));
+ recycle_header_field(packet->header_field,
+ bt_stream_class_borrow_trace_inline(
+ packet->stream->class));
} else {
- bt_field_wrapper_destroy(packet->header);
+ bt_field_wrapper_destroy(packet->header_field);
}
}
- if (packet->context) {
+ if (packet->context_field) {
if (packet->stream) {
BT_LOGD_STR("Recycling packet's context field.");
- bt_packet_context_field_recycle(packet->context,
- bt_stream_borrow_class(packet->stream));
+ recycle_context_field(packet->context_field,
+ packet->stream->class);
} else {
- bt_field_wrapper_destroy(packet->context);
+ bt_field_wrapper_destroy(packet->context_field);
}
}
- bt_clock_value_set_finalize(&packet->begin_cv_set);
- bt_clock_value_set_finalize(&packet->end_cv_set);
+ if (packet->default_beginning_cv) {
+ BT_LOGD_STR("Recycling beginning clock value.");
+ bt_clock_value_recycle(packet->default_beginning_cv);
+ }
+
+ if (packet->default_end_cv) {
+ BT_LOGD_STR("Recycling end clock value.");
+ bt_clock_value_recycle(packet->default_end_cv);
+ }
+
BT_LOGD_STR("Putting packet's stream.");
bt_put(packet->stream);
g_free(packet);
struct bt_packet *bt_packet_new(struct bt_stream *stream)
{
struct bt_packet *packet = NULL;
- struct bt_stream_class *stream_class = NULL;
struct bt_trace *trace = NULL;
BT_ASSERT(stream);
- BT_LOGD("Creating packet object: stream-addr=%p, "
- "stream-name=\"%s\", stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64,
- stream, bt_stream_get_name(stream),
- stream->stream_class,
- bt_stream_class_get_name(stream->stream_class),
- bt_stream_class_get_id(stream->stream_class));
- stream_class = bt_stream_borrow_class(stream);
- BT_ASSERT(stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
- BT_ASSERT(trace);
+ BT_LIB_LOGD("Creating packet object: %![stream-]+s", stream);
packet = g_new0(struct bt_packet, 1);
if (!packet) {
BT_LOGE_STR("Failed to allocate one packet object.");
- goto end;
+ goto error;
}
bt_object_init_shared(&packet->base,
(bt_object_release_func) bt_packet_recycle);
packet->stream = bt_get(stream);
+ trace = bt_stream_class_borrow_trace_inline(stream->class);
+ BT_ASSERT(trace);
- if (trace->packet_header_field_type) {
- BT_LOGD("Creating initial packet header field: ft-addr=%p",
- trace->packet_header_field_type);
- packet->header = bt_field_wrapper_create(
+ if (trace->packet_header_ft) {
+ BT_LOGD_STR("Creating initial packet header field.");
+ packet->header_field = bt_field_wrapper_create(
&trace->packet_header_field_pool,
- (void *) trace->packet_header_field_type);
- if (!packet->header) {
- BT_LOGE("Cannot create packet header field wrapper.");
- BT_PUT(packet);
- goto end;
+ trace->packet_header_ft);
+ if (!packet->header_field) {
+ BT_LOGE_STR("Cannot create packet header field wrapper.");
+ goto error;
}
}
- if (stream->stream_class->packet_context_field_type) {
- BT_LOGD("Creating initial packet context field: ft-addr=%p",
- stream->stream_class->packet_context_field_type);
- packet->context = bt_field_wrapper_create(
- &stream_class->packet_context_field_pool,
- (void *) stream->stream_class->packet_context_field_type);
- if (!packet->context) {
- BT_LOGE("Cannot create packet context field wrapper.");
- BT_PUT(packet);
- goto end;
+ if (stream->class->packet_context_ft) {
+ BT_LOGD_STR("Creating initial packet context field.");
+ packet->context_field = bt_field_wrapper_create(
+ &stream->class->packet_context_field_pool,
+ stream->class->packet_context_ft);
+ if (!packet->context_field) {
+ BT_LOGE_STR("Cannot create packet context field wrapper.");
+ goto error;
}
}
- if (bt_clock_value_set_initialize(&packet->begin_cv_set)) {
- BT_PUT(packet);
- goto end;
- }
-
- if (bt_clock_value_set_initialize(&packet->end_cv_set)) {
- BT_PUT(packet);
- goto end;
- }
-
- bt_packet_reset_avail(packet);
- BT_LOGD("Created packet object: addr=%p", packet);
-
-end:
- return packet;
-}
-
-static inline
-uint64_t get_uint_field_value(struct bt_field *parent_field, const char *name)
-{
- uint64_t val = UINT64_C(-1);
- struct bt_field *field = bt_field_structure_borrow_field_by_name(
- parent_field, name);
- int ret;
-
- if (!field) {
- goto end;
- }
-
- BT_ASSERT(bt_field_is_integer(field));
- BT_ASSERT(!bt_field_type_integer_is_signed(
- bt_field_borrow_type(field)));
- ret = bt_field_integer_unsigned_get_value(field, &val);
- BT_ASSERT(ret == 0);
-
-end:
- return val;
-}
-
-static inline
-void set_packet_prop_uint64(struct bt_packet_prop_uint64 *prop, uint64_t val)
-{
- BT_ASSERT(prop);
- prop->value = val;
- prop->avail = BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE;
-}
-
-static inline
-int set_packet_default_clock_value(struct bt_field *pkt_ctx_field,
- const char *field_name, struct bt_clock_value_set *cv_set)
-{
- int ret = 0;
- uint64_t val = UINT64_C(-1);
- struct bt_field *field = bt_field_structure_borrow_field_by_name(
- pkt_ctx_field, field_name);
- struct bt_clock_class *clock_class;
-
- if (!field) {
- goto end;
- }
-
- BT_ASSERT(bt_field_is_integer(field));
- BT_ASSERT(!bt_field_type_integer_is_signed(
- bt_field_borrow_type(field)));
- clock_class = bt_field_type_integer_borrow_mapped_clock_class(
- bt_field_borrow_type(field));
- if (!clock_class) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(field, &val);
- BT_ASSERT(ret == 0);
- ret = bt_clock_value_set_set_clock_value(cv_set, clock_class,
- val, true);
-
-end:
- return ret;
-}
-
-BT_HIDDEN
-int bt_packet_set_properties(struct bt_packet *packet)
-{
- struct bt_field *pkt_context_field;
- uint64_t val;
- int ret = 0;
-
- BT_ASSERT(!packet->props_are_set);
-
- pkt_context_field = bt_packet_borrow_context(packet);
- if (!pkt_context_field) {
- goto end;
- }
-
- /* Discarded event counter */
- val = get_uint_field_value(pkt_context_field, "events_discarded");
- if (val != UINT64_C(-1)) {
- set_packet_prop_uint64(&packet->discarded_event_counter, val);
- }
-
- /* Sequence number */
- val = get_uint_field_value(pkt_context_field, "packet_seq_num");
- if (val != UINT64_C(-1)) {
- set_packet_prop_uint64(&packet->seq_num, val);
- }
-
- /* Beginning and end times */
- ret = set_packet_default_clock_value(pkt_context_field,
- "timestamp_begin", &packet->begin_cv_set);
- if (ret) {
- goto end;
- }
-
- ret = set_packet_default_clock_value(pkt_context_field,
- "timestamp_end", &packet->end_cv_set);
- if (ret) {
- goto end;
- }
-
- /* Information from previous packet */
- if (packet->prev_packet_info.avail ==
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE) {
- /* Discarded event count */
- if (packet->prev_packet_info.discarded_event_counter.avail ==
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE) {
- BT_ASSERT(packet->discarded_event_counter.avail ==
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE);
- set_packet_prop_uint64(&packet->discarded_event_count,
- packet->discarded_event_counter.value -
- packet->prev_packet_info.discarded_event_counter.value);
+ if (stream->class->default_clock_class) {
+ if (stream->class->packets_have_default_beginning_cv) {
+ packet->default_beginning_cv = bt_clock_value_create(
+ stream->class->default_clock_class);
+ if (!packet->default_beginning_cv) {
+ /* bt_clock_value_create() logs errors */
+ goto error;
+ }
}
- /* Discarded packet count */
- if (packet->prev_packet_info.seq_num.avail ==
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE) {
- BT_ASSERT(packet->seq_num.avail ==
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE);
- set_packet_prop_uint64(&packet->discarded_packet_count,
- packet->seq_num.value -
- packet->prev_packet_info.seq_num.value - 1);
+ if (stream->class->packets_have_default_end_cv) {
+ packet->default_end_cv = bt_clock_value_create(
+ stream->class->default_clock_class);
+ if (!packet->default_end_cv) {
+ /* bt_clock_value_create() logs errors */
+ goto error;
+ }
}
}
-end:
- return ret;
-}
-
-static
-int snapshot_prev_packet_properties(struct bt_packet *packet,
- enum bt_packet_previous_packet_availability prev_packet_avail,
- struct bt_packet *prev_packet)
-{
- int ret = 0;
- struct bt_clock_value *prev_packet_default_end_cv;
-
- if (!prev_packet) {
- goto end;
- }
-
- if (!prev_packet->props_are_set) {
- ret = bt_packet_set_properties(prev_packet);
- if (ret) {
- BT_LIB_LOGE("Cannot update previous packet's properties: "
- "%![prev-packet-]+a", prev_packet);
- goto end;
- }
- }
-
- packet->prev_packet_info.avail = prev_packet_avail;
- prev_packet_default_end_cv = prev_packet->end_cv_set.default_cv;
-
- /* End time */
- if (prev_packet_default_end_cv) {
- /* Copy clock value */
- packet->prev_packet_info.default_end_cv.cv =
- bt_clock_value_create(
- prev_packet_default_end_cv->clock_class);
- if (!packet->prev_packet_info.default_end_cv.cv) {
- BT_LIB_LOGE("Cannot create a clock value from a clock class: "
- "%![cc-]+K",
- prev_packet_default_end_cv->clock_class);
- ret = -1;
- goto end;
- }
-
- bt_clock_value_set_raw_value(
- packet->prev_packet_info.default_end_cv.cv,
- prev_packet_default_end_cv->value);
- packet->prev_packet_info.default_end_cv.avail =
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE;
- }
-
- /* Discarded event counter */
- packet->prev_packet_info.discarded_event_counter =
- prev_packet->discarded_event_counter;
+ reset_counter_snapshots(packet);
+ BT_LIB_LOGD("Created packet object: %!+a", packet);
+ goto end;
- /* Sequence number */
- packet->prev_packet_info.seq_num = prev_packet->seq_num;
+error:
+ BT_PUT(packet);
end:
- return ret;
+ return packet;
}
-struct bt_packet *bt_packet_create(struct bt_stream *stream,
- enum bt_packet_previous_packet_availability prev_packet_avail,
- struct bt_packet *prev_packet)
+struct bt_packet *bt_packet_create(struct bt_stream *stream)
{
struct bt_packet *packet = NULL;
- int ret;
BT_ASSERT_PRE_NON_NULL(stream, "Stream");
- BT_ASSERT_PRE(!prev_packet || prev_packet->stream == stream,
- "New packet's and previous packet's stream are not the same: "
- "%![new-packet-stream-]+s, %![prev-packet]+a, "
- "%![prev-packet-stream]+s", stream, prev_packet,
- prev_packet->stream);
- BT_ASSERT_PRE(
- prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE ||
- prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE ||
- prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE,
- "Invalid previous packet availability value: val=%d",
- prev_packet_avail);
- BT_ASSERT_PRE(!prev_packet ||
- prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE,
- "Previous packet is available, but previous packet is NULL.");
packet = bt_object_pool_create_object(&stream->packet_pool);
if (unlikely(!packet)) {
BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: "
goto end;
}
- if (unlikely(!packet->stream)) {
+ if (likely(!packet->stream)) {
packet->stream = stream;
bt_object_get_no_null_check_no_parent_check(
&packet->stream->base);
}
- ret = snapshot_prev_packet_properties(packet, prev_packet_avail,
- prev_packet);
- if (ret) {
- /* Recycle */
- BT_PUT(packet);
- goto end;
- }
-
- if (prev_packet) {
- bt_packet_validate_properties(prev_packet);
- bt_packet_set_is_frozen(prev_packet, true);
- }
-
- goto end;
-
end:
return packet;
}
-int bt_packet_move_header(struct bt_packet *packet,
+int bt_packet_move_header_field(struct bt_packet *packet,
struct bt_packet_header_field *header_field)
{
struct bt_trace *trace;
struct bt_field_wrapper *field_wrapper = (void *) header_field;
- BT_ASSERT_PRE_NON_NULL(packet, "Event");
+ BT_ASSERT_PRE_NON_NULL(packet, "Packet");
BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field");
- BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet);
- trace = bt_stream_class_borrow_trace(
- bt_stream_borrow_class(packet->stream));
- BT_ASSERT_PRE(trace->packet_header_field_type,
+ BT_ASSERT_PRE_PACKET_HOT(packet);
+ trace = bt_stream_class_borrow_trace_inline(packet->stream->class);
+ BT_ASSERT_PRE(trace->packet_header_ft,
"Trace has no packet header field type: %!+t",
trace);
-
- /* TODO: compare field types (precondition) */
+ BT_ASSERT_PRE(field_wrapper->field->type ==
+ trace->packet_header_ft,
+ "Unexpected packet header field's type: "
+ "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type,
+ trace->packet_header_ft);
/* Recycle current header field: always exists */
- BT_ASSERT(packet->header);
- bt_packet_header_field_recycle(packet->header, trace);
+ BT_ASSERT(packet->header_field);
+ recycle_header_field(packet->header_field, trace);
/* Move new field */
- packet->header = field_wrapper;
+ packet->header_field = field_wrapper;
return 0;
}
-int bt_packet_move_context(struct bt_packet *packet,
+int bt_packet_move_context_field(struct bt_packet *packet,
struct bt_packet_context_field *context_field)
{
struct bt_stream_class *stream_class;
struct bt_field_wrapper *field_wrapper = (void *) context_field;
- BT_ASSERT_PRE_NON_NULL(packet, "Event");
+ BT_ASSERT_PRE_NON_NULL(packet, "Packet");
BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field");
BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet);
- stream_class = bt_stream_borrow_class(packet->stream);
- BT_ASSERT_PRE(stream_class->packet_context_field_type,
+ stream_class = packet->stream->class;
+ BT_ASSERT_PRE(stream_class->packet_context_ft,
"Stream class has no packet context field type: %!+S",
stream_class);
-
- /* TODO: compare field types (precondition) */
+ BT_ASSERT_PRE(field_wrapper->field->type ==
+ stream_class->packet_context_ft,
+ "Unexpected packet header field's type: "
+ "%![ft-]+F, %![expected-ft-]+F", field_wrapper->field->type,
+ stream_class->packet_context_ft);
/* Recycle current context field: always exists */
- BT_ASSERT(packet->context);
- bt_packet_context_field_recycle(packet->context, stream_class);
+ BT_ASSERT(packet->context_field);
+ recycle_context_field(packet->context_field, stream_class);
/* Move new field */
- packet->context = field_wrapper;
+ packet->context_field = field_wrapper;
return 0;
}
-enum bt_packet_property_availability
-bt_packet_borrow_default_beginning_clock_value(struct bt_packet *packet,
- struct bt_clock_value **clock_value)
+int bt_packet_set_default_beginning_clock_value(struct bt_packet *packet,
+ uint64_t value_cycles)
{
- enum bt_packet_property_availability avail =
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE;
+ struct bt_stream_class *sc;
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
- *clock_value = packet->begin_cv_set.default_cv;
- if (!*clock_value) {
- avail = BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- }
-
- return avail;
+ BT_ASSERT_PRE_PACKET_HOT(packet);
+ sc = packet->stream->class;
+ BT_ASSERT(sc);
+ BT_ASSERT_PRE(sc->default_clock_class,
+ "Packet's stream class has no default clock class: "
+ "%![packet-]+a, %![sc-]+S", packet, sc);
+ BT_ASSERT_PRE(sc->packets_have_default_beginning_cv,
+ "Packet's stream class indicates that its packets have "
+ "no default beginning clock value: %![packet-]+a, %![sc-]+S",
+ packet, sc);
+ BT_ASSERT(packet->default_beginning_cv);
+ bt_clock_value_set_value_inline(packet->default_beginning_cv, value_cycles);
+ BT_LIB_LOGV("Set packet's default beginning clock value: "
+ "%![packet-]+a, value=%" PRIu64, value_cycles);
+ return 0;
}
-enum bt_packet_property_availability
-bt_packet_borrow_default_end_clock_value(struct bt_packet *packet,
- struct bt_clock_value **clock_value)
+enum bt_clock_value_status bt_packet_borrow_default_beginning_clock_value(
+ struct bt_packet *packet, struct bt_clock_value **clock_value)
{
- enum bt_packet_property_availability avail =
- BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE;
-
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
- *clock_value = packet->end_cv_set.default_cv;
- if (!*clock_value) {
- avail = BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE;
- }
-
- return avail;
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)");
+ *clock_value = packet->default_beginning_cv;
+ return BT_CLOCK_VALUE_STATUS_KNOWN;
}
-enum bt_packet_previous_packet_availability
-bt_packet_get_previous_packet_availability(struct bt_packet *packet)
+int bt_packet_set_default_end_clock_value(struct bt_packet *packet,
+ uint64_t value_cycles)
{
+ struct bt_stream_class *sc;
+
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- return packet->prev_packet_info.avail;
+ BT_ASSERT_PRE_PACKET_HOT(packet);
+ sc = packet->stream->class;
+ BT_ASSERT(sc);
+ BT_ASSERT_PRE(sc->default_clock_class,
+ "Packet's stream class has no default clock class: "
+ "%![packet-]+a, %![sc-]+S", packet, sc);
+ BT_ASSERT_PRE(sc->packets_have_default_end_cv,
+ "Packet's stream class indicates that its packets have "
+ "no default end clock value: %![packet-]+a, %![sc-]+S",
+ packet, sc);
+ BT_ASSERT(packet->default_end_cv);
+ bt_clock_value_set_value_inline(packet->default_end_cv, value_cycles);
+ BT_LIB_LOGV("Set packet's default end clock value: "
+ "%![packet-]+a, value=%" PRIu64, value_cycles);
+ return 0;
}
-enum bt_packet_property_availability
-bt_packet_borrow_previous_packet_default_end_clock_value(
+enum bt_clock_value_status bt_packet_borrow_default_end_clock_value(
struct bt_packet *packet, struct bt_clock_value **clock_value)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value");
- *clock_value = packet->prev_packet_info.default_end_cv.cv;
- return packet->prev_packet_info.default_end_cv.avail;
+ BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value (output)");
+ *clock_value = packet->default_end_cv;
+ return BT_CLOCK_VALUE_STATUS_KNOWN;
}
-enum bt_packet_property_availability bt_packet_get_discarded_event_counter(
- struct bt_packet *packet, uint64_t *counter)
+enum bt_property_availability bt_packet_get_discarded_event_counter_snapshot(
+ struct bt_packet *packet, uint64_t *value)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(counter, "Counter");
- *counter = packet->discarded_event_counter.value;
- return packet->discarded_event_counter.avail;
+ BT_ASSERT_PRE_NON_NULL(value, "Value (output)");
+ *value = packet->discarded_event_counter_snapshot.value;
+ return packet->discarded_event_counter_snapshot.base.avail;
}
-enum bt_packet_property_availability bt_packet_get_sequence_number(
- struct bt_packet *packet, uint64_t *sequence_number)
+int bt_packet_set_discarded_event_counter_snapshot(struct bt_packet *packet,
+ uint64_t value)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(sequence_number, "Sequence number");
- *sequence_number = packet->seq_num.value;
- return packet->seq_num.avail;
+ BT_ASSERT_PRE_PACKET_HOT(packet);
+ BT_ASSERT_PRE(packet->stream->class->packets_have_discarded_event_counter_snapshot,
+ "Packet's stream's discarded event counter is not enabled: "
+ "%![packet-]+a", packet);
+ bt_property_uint_set(&packet->discarded_event_counter_snapshot, value);
+ return 0;
}
-enum bt_packet_property_availability bt_packet_get_discarded_event_count(
- struct bt_packet *packet, uint64_t *count)
+enum bt_property_availability bt_packet_get_packet_counter_snapshot(
+ struct bt_packet *packet, uint64_t *value)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(count, "Count");
- *count = packet->discarded_event_count.value;
- return packet->discarded_event_count.avail;
+ BT_ASSERT_PRE_NON_NULL(value, "Value (output)");
+ *value = packet->packet_counter_snapshot.value;
+ return packet->packet_counter_snapshot.base.avail;
}
-enum bt_packet_property_availability bt_packet_get_discarded_packet_count(
- struct bt_packet *packet, uint64_t *count)
+int bt_packet_set_packet_counter_snapshot(struct bt_packet *packet,
+ uint64_t value)
{
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
- BT_ASSERT_PRE_NON_NULL(count, "Count");
- *count = packet->discarded_packet_count.value;
- return packet->discarded_packet_count.avail;
+ BT_ASSERT_PRE_PACKET_HOT(packet);
+ BT_ASSERT_PRE(packet->stream->class->packets_have_packet_counter_snapshot,
+ "Packet's stream's packet counter is not enabled: "
+ "%![packet-]+a", packet);
+ bt_property_uint_set(&packet->packet_counter_snapshot, value);
+ return 0;
}
-
--- /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 "RESOLVE-FIELD-PATH"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
+#include <babeltrace/ctf-ir/field-path-internal.h>
+#include <babeltrace/ctf-ir/field-path.h>
+#include <babeltrace/ctf-ir/resolve-field-path-internal.h>
+#include <limits.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <glib.h>
+
+static
+bool find_field_type_recursive(struct bt_field_type *ft,
+ struct bt_field_type *tgt_ft, struct bt_field_path *field_path)
+{
+ bool found = false;
+
+ if (tgt_ft == ft) {
+ found = true;
+ goto end;
+ }
+
+ switch (ft->id) {
+ case BT_FIELD_TYPE_ID_STRUCTURE:
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_field_type_named_field_types_container *container_ft =
+ (void *) ft;
+ uint64_t i;
+
+ for (i = 0; i < container_ft->named_fts->len; i++) {
+ struct bt_named_field_type *named_ft =
+ BT_FIELD_TYPE_NAMED_FT_AT_INDEX(
+ container_ft, i);
+
+ g_array_append_val(field_path->indexes, i);
+ found = find_field_type_recursive(named_ft->ft,
+ tgt_ft, field_path);
+ if (found) {
+ goto end;
+ }
+
+ g_array_set_size(field_path->indexes,
+ field_path->indexes->len - 1);
+ }
+
+ break;
+ }
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ {
+ struct bt_field_type_array *array_ft = (void *) ft;
+
+ found = find_field_type_recursive(array_ft->element_ft,
+ tgt_ft, field_path);
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return found;
+}
+
+static
+int find_field_type(struct bt_field_type *root_ft,
+ enum bt_scope root_scope, struct bt_field_type *tgt_ft,
+ struct bt_field_path **ret_field_path)
+{
+ int ret = 0;
+ struct bt_field_path *field_path = NULL;
+
+ if (!root_ft) {
+ goto end;
+ }
+
+ field_path = bt_field_path_create();
+ if (!field_path) {
+ ret = -1;
+ goto end;
+ }
+
+ field_path->root = root_scope;
+ if (!find_field_type_recursive(root_ft, tgt_ft, field_path)) {
+ /* Not found here */
+ BT_PUT(field_path);
+ }
+
+end:
+ *ret_field_path = field_path;
+ return ret;
+}
+
+static
+struct bt_field_path *find_field_type_in_ctx(struct bt_field_type *ft,
+ struct bt_resolve_field_path_context *ctx)
+{
+ struct bt_field_path *field_path = NULL;
+ int ret;
+
+ ret = find_field_type(ctx->packet_header, BT_SCOPE_PACKET_HEADER,
+ ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+ ret = find_field_type(ctx->packet_context, BT_SCOPE_PACKET_CONTEXT,
+ ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+ ret = find_field_type(ctx->event_header, BT_SCOPE_EVENT_HEADER,
+ ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+ ret = find_field_type(ctx->event_common_context,
+ BT_SCOPE_EVENT_COMMON_CONTEXT, ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+ ret = find_field_type(ctx->event_specific_context,
+ BT_SCOPE_EVENT_SPECIFIC_CONTEXT, ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+ ret = find_field_type(ctx->event_payload, BT_SCOPE_EVENT_PAYLOAD,
+ ft, &field_path);
+ if (ret || field_path) {
+ goto end;
+ }
+
+end:
+ return field_path;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+bool target_is_before_source(struct bt_field_path *src_field_path,
+ struct bt_field_path *tgt_field_path)
+{
+ bool is_valid = true;
+ uint64_t src_i = 0, tgt_i = 0;
+
+ if (tgt_field_path->root < src_field_path->root) {
+ goto end;
+ }
+
+ if (tgt_field_path->root > src_field_path->root) {
+ is_valid = false;
+ goto end;
+ }
+
+ BT_ASSERT(tgt_field_path->root == src_field_path->root);
+
+ while (src_i < src_field_path->indexes->len &&
+ tgt_i < tgt_field_path->indexes->len) {
+ uint64_t src_index = bt_field_path_get_index_by_index_inline(
+ src_field_path, src_i);
+ uint64_t tgt_index = bt_field_path_get_index_by_index_inline(
+ tgt_field_path, tgt_i);
+
+ if (tgt_index > src_index) {
+ is_valid = false;
+ goto end;
+ }
+
+ src_i++;
+ tgt_i++;
+ }
+
+end:
+ return is_valid;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+struct bt_field_type *borrow_root_field_type(
+ struct bt_resolve_field_path_context *ctx, enum bt_scope scope)
+{
+ switch (scope) {
+ case BT_SCOPE_PACKET_HEADER:
+ return ctx->packet_header;
+ case BT_SCOPE_PACKET_CONTEXT:
+ return ctx->packet_context;
+ case BT_SCOPE_EVENT_HEADER:
+ return ctx->event_header;
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ return ctx->event_common_context;
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ return ctx->event_specific_context;
+ case BT_SCOPE_EVENT_PAYLOAD:
+ return ctx->event_payload;
+ default:
+ abort();
+ }
+
+ return NULL;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+struct bt_field_type *borrow_child_field_type(struct bt_field_type *parent_ft,
+ uint64_t index, bool *advance)
+{
+ struct bt_field_type *child_ft = NULL;
+
+ switch (parent_ft->id) {
+ case BT_FIELD_TYPE_ID_STRUCTURE:
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_named_field_type *named_ft =
+ BT_FIELD_TYPE_NAMED_FT_AT_INDEX(parent_ft, index);
+
+ child_ft = named_ft->ft;
+ *advance = true;
+ break;
+ }
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ {
+ struct bt_field_type_array *array_ft = (void *) parent_ft;
+
+ child_ft = array_ft->element_ft;
+ *advance = false;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return child_ft;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+bool target_field_path_in_different_scope_has_struct_ft_only(
+ struct bt_field_path *src_field_path,
+ struct bt_field_path *tgt_field_path,
+ struct bt_resolve_field_path_context *ctx)
+{
+ bool is_valid = true;
+ uint64_t i = 0;
+ struct bt_field_type *ft;
+
+ if (src_field_path->root == tgt_field_path->root) {
+ goto end;
+ }
+
+ ft = borrow_root_field_type(ctx, tgt_field_path->root);
+
+ while (i < tgt_field_path->indexes->len) {
+ uint64_t index = bt_field_path_get_index_by_index_inline(
+ tgt_field_path, i);
+ bool advance;
+
+ if (ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY ||
+ ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY ||
+ ft->id == BT_FIELD_TYPE_ID_VARIANT) {
+ is_valid = false;
+ goto end;
+ }
+
+ ft = borrow_child_field_type(ft, index, &advance);
+
+ if (advance) {
+ i++;
+ }
+ }
+
+end:
+ return is_valid;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+bool lca_is_structure_field_type(struct bt_field_path *src_field_path,
+ struct bt_field_path *tgt_field_path,
+ struct bt_resolve_field_path_context *ctx)
+{
+ bool is_valid = true;
+ struct bt_field_type *src_ft;
+ struct bt_field_type *tgt_ft;
+ struct bt_field_type *prev_ft = NULL;
+ uint64_t src_i = 0, tgt_i = 0;
+
+ if (src_field_path->root != tgt_field_path->root) {
+ goto end;
+ }
+
+ src_ft = borrow_root_field_type(ctx, src_field_path->root);
+ tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root);
+ BT_ASSERT(src_ft);
+ BT_ASSERT(tgt_ft);
+
+ while (src_i < src_field_path->indexes->len &&
+ tgt_i < tgt_field_path->indexes->len) {
+ bool advance;
+ uint64_t src_index = bt_field_path_get_index_by_index_inline(
+ src_field_path, src_i);
+ uint64_t tgt_index = bt_field_path_get_index_by_index_inline(
+ tgt_field_path, tgt_i);
+
+ if (src_ft != tgt_ft) {
+ if (!prev_ft) {
+ /*
+ * This is correct: the LCA is the root
+ * scope field type, which must be a
+ * structure field type.
+ */
+ break;
+ }
+
+ if (prev_ft->id != BT_FIELD_TYPE_ID_STRUCTURE) {
+ is_valid = false;
+ }
+
+ break;
+ }
+
+ prev_ft = src_ft;
+ src_ft = borrow_child_field_type(src_ft, src_index, &advance);
+
+ if (advance) {
+ src_i++;
+ }
+
+ tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance);
+
+ if (advance) {
+ tgt_i++;
+ }
+ }
+
+end:
+ return is_valid;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+bool lca_to_target_has_struct_ft_only(struct bt_field_path *src_field_path,
+ struct bt_field_path *tgt_field_path,
+ struct bt_resolve_field_path_context *ctx)
+{
+ bool is_valid = true;
+ struct bt_field_type *src_ft;
+ struct bt_field_type *tgt_ft;
+ uint64_t src_i = 0, tgt_i = 0;
+
+ if (src_field_path->root != tgt_field_path->root) {
+ goto end;
+ }
+
+ src_ft = borrow_root_field_type(ctx, src_field_path->root);
+ tgt_ft = borrow_root_field_type(ctx, tgt_field_path->root);
+ BT_ASSERT(src_ft);
+ BT_ASSERT(tgt_ft);
+ BT_ASSERT(src_ft == tgt_ft);
+
+ /* Find LCA */
+ while (src_i < src_field_path->indexes->len &&
+ tgt_i < tgt_field_path->indexes->len) {
+ bool advance;
+ uint64_t src_index = bt_field_path_get_index_by_index_inline(
+ src_field_path, src_i);
+ uint64_t tgt_index = bt_field_path_get_index_by_index_inline(
+ tgt_field_path, tgt_i);
+
+ if (src_i != tgt_i) {
+ /* Next FT is different: LCA is `tgt_ft` */
+ break;
+ }
+
+ src_ft = borrow_child_field_type(src_ft, src_index, &advance);
+
+ if (advance) {
+ src_i++;
+ }
+
+ tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance);
+
+ if (advance) {
+ tgt_i++;
+ }
+ }
+
+ /* Only structure field types to the target */
+ while (tgt_i < tgt_field_path->indexes->len) {
+ bool advance;
+ uint64_t tgt_index = bt_field_path_get_index_by_index_inline(
+ tgt_field_path, tgt_i);
+
+ if (tgt_ft->id == BT_FIELD_TYPE_ID_STATIC_ARRAY ||
+ tgt_ft->id == BT_FIELD_TYPE_ID_DYNAMIC_ARRAY ||
+ tgt_ft->id == BT_FIELD_TYPE_ID_VARIANT) {
+ is_valid = false;
+ goto end;
+ }
+
+ tgt_ft = borrow_child_field_type(tgt_ft, tgt_index, &advance);
+
+ if (advance) {
+ tgt_i++;
+ }
+ }
+
+end:
+ return is_valid;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline
+bool field_path_is_valid(struct bt_field_type *src_ft,
+ struct bt_field_type *tgt_ft,
+ struct bt_resolve_field_path_context *ctx)
+{
+ bool is_valid = true;
+ struct bt_field_path *src_field_path = find_field_type_in_ctx(
+ src_ft, ctx);
+ struct bt_field_path *tgt_field_path = find_field_type_in_ctx(
+ tgt_ft, ctx);
+
+ if (!src_field_path) {
+ BT_ASSERT_PRE_MSG("Cannot find requesting field type in "
+ "resolving context: %!+F", src_ft);
+ is_valid = false;
+ goto end;
+ }
+
+ if (!tgt_field_path) {
+ BT_ASSERT_PRE_MSG("Cannot find target field type in "
+ "resolving context: %!+F", tgt_ft);
+ is_valid = false;
+ goto end;
+ }
+
+ /* Target must be before source */
+ if (!target_is_before_source(src_field_path, tgt_field_path)) {
+ BT_ASSERT_PRE_MSG("Target field type is located after "
+ "requesting field type: %![req-ft-]+F, %![tgt-ft-]+F",
+ src_ft, tgt_ft);
+ is_valid = false;
+ goto end;
+ }
+
+ /*
+ * If target is in a different scope than source, there are no
+ * array or variant field types on the way to the target.
+ */
+ if (!target_field_path_in_different_scope_has_struct_ft_only(
+ src_field_path, tgt_field_path, ctx)) {
+ BT_ASSERT_PRE_MSG("Target field type is located in a "
+ "different scope than requesting field type, "
+ "but within an array or a variant field type: "
+ "%![req-ft-]+F, %![tgt-ft-]+F",
+ src_ft, tgt_ft);
+ is_valid = false;
+ goto end;
+ }
+
+ /* Same scope: LCA must be a structure field type */
+ if (!lca_is_structure_field_type(src_field_path, tgt_field_path, ctx)) {
+ BT_ASSERT_PRE_MSG("Lowest common ancestor of target and "
+ "requesting field types is not a structure field type: "
+ "%![req-ft-]+F, %![tgt-ft-]+F",
+ src_ft, tgt_ft);
+ is_valid = false;
+ goto end;
+ }
+
+ /* Same scope: path from LCA to target has no array/variant FTs */
+ if (!lca_to_target_has_struct_ft_only(src_field_path, tgt_field_path,
+ ctx)) {
+ BT_ASSERT_PRE_MSG("Path from lowest common ancestor of target "
+ "and requesting field types to target field type "
+ "contains an array or a variant field type: "
+ "%![req-ft-]+F, %![tgt-ft-]+F", src_ft, tgt_ft);
+ is_valid = false;
+ goto end;
+ }
+
+end:
+ bt_put(src_field_path);
+ bt_put(tgt_field_path);
+ return is_valid;
+}
+
+static
+struct bt_field_path *resolve_field_path(struct bt_field_type *src_ft,
+ struct bt_field_type *tgt_ft,
+ struct bt_resolve_field_path_context *ctx)
+{
+ BT_ASSERT_PRE(field_path_is_valid(src_ft, tgt_ft, ctx),
+ "Invalid target field type: %![req-ft-]+F, %![tgt-ft-]+F",
+ src_ft, tgt_ft);
+ return find_field_type_in_ctx(tgt_ft, ctx);
+}
+
+BT_HIDDEN
+int bt_resolve_field_paths(struct bt_field_type *ft,
+ struct bt_resolve_field_path_context *ctx)
+{
+ int ret = 0;
+
+ BT_ASSERT(ft);
+
+ /* Resolving part for dynamic array and variant field types */
+ switch (ft->id) {
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ {
+ struct bt_field_type_dynamic_array *dyn_array_ft = (void *) ft;
+
+ if (dyn_array_ft->length_ft) {
+ BT_ASSERT(!dyn_array_ft->length_field_path);
+ dyn_array_ft->length_field_path = resolve_field_path(
+ ft, dyn_array_ft->length_ft, ctx);
+ if (!dyn_array_ft->length_field_path) {
+ ret = -1;
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_field_type_variant *var_ft = (void *) ft;
+
+ if (var_ft->selector_ft) {
+ BT_ASSERT(!var_ft->selector_field_path);
+ var_ft->selector_field_path =
+ resolve_field_path(ft,
+ var_ft->selector_ft, ctx);
+ if (!var_ft->selector_field_path) {
+ ret = -1;
+ goto end;
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+ /* Recursive part */
+ switch (ft->id) {
+ case BT_FIELD_TYPE_ID_STRUCTURE:
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ struct bt_field_type_named_field_types_container *container_ft =
+ (void *) ft;
+ uint64_t i;
+
+ for (i = 0; i < container_ft->named_fts->len; i++) {
+ struct bt_named_field_type *named_ft =
+ BT_FIELD_TYPE_NAMED_FT_AT_INDEX(
+ container_ft, i);
+
+ ret = bt_resolve_field_paths(named_ft->ft, ctx);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ {
+ struct bt_field_type_array *array_ft = (void *) ft;
+
+ ret = bt_resolve_field_paths(array_ft->element_ft, ctx);
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+++ /dev/null
-/*
- * resolve.c
- *
- * Babeltrace - CTF IR: 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 "RESOLVE"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/resolve-internal.h>
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/field-path.h>
-#include <babeltrace/ctf-ir/field-path-internal.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/values.h>
-#include <babeltrace/types.h>
-#include <babeltrace/assert-internal.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <glib.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_field_type *type;
- int index;
-};
-
-/*
- * The current context of the resolving engine.
- *
- * `scopes` contain the 6 CTF scope field types (see CTF, sect. 7.3.2)
- * in the following order:
- *
- * * Packet header
- * * Packet context
- * * Event header
- * * Stream event context
- * * Event context
- * * Event payload
- */
-struct resolve_context {
- struct bt_value *environment;
- struct bt_field_type *scopes[6];
-
- /* Root scope being visited */
- enum bt_scope root_scope;
- type_stack *type_stack;
- struct bt_field_type *cur_field_type;
-};
-
-/* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
-static const char * const absolute_path_prefixes[] = {
- [BT_SCOPE_ENV] = "env.",
- [BT_SCOPE_TRACE_PACKET_HEADER] = "trace.packet.header.",
- [BT_SCOPE_STREAM_PACKET_CONTEXT] = "stream.packet.context.",
- [BT_SCOPE_STREAM_EVENT_HEADER] = "stream.event.header.",
- [BT_SCOPE_STREAM_EVENT_CONTEXT] = "stream.event.context.",
- [BT_SCOPE_EVENT_CONTEXT] = "event.context.",
- [BT_SCOPE_EVENT_FIELDS] = "event.fields.",
-};
-
-/* Number of path tokens used for the absolute prefixes */
-static const int absolute_path_prefix_ptoken_counts[] = {
- [BT_SCOPE_ENV] = 1,
- [BT_SCOPE_TRACE_PACKET_HEADER] = 3,
- [BT_SCOPE_STREAM_PACKET_CONTEXT] = 3,
- [BT_SCOPE_STREAM_EVENT_HEADER] = 3,
- [BT_SCOPE_STREAM_EVENT_CONTEXT] = 3,
- [BT_SCOPE_EVENT_CONTEXT] = 2,
- [BT_SCOPE_EVENT_FIELDS] = 2,
-};
-
-/*
- * Destroys a type stack frame.
- */
-static
-void type_stack_destroy_notify(gpointer data)
-{
- struct type_stack_frame *frame = data;
-
- BT_PUT(frame->type);
- g_free(frame);
-}
-
-/*
- * Creates a type stack.
- *
- * Return value is owned by the caller.
- */
-static
-type_stack *type_stack_create(void)
-{
- return g_ptr_array_new_with_free_func(type_stack_destroy_notify);
-}
-
-/*
- * Destroys a type stack.
- */
-static
-void type_stack_destroy(type_stack *stack)
-{
- g_ptr_array_free(stack, TRUE);
-}
-
-/*
- * Pushes a field type onto a type stack.
- *
- * `type` is owned by the caller (stack frame gets a new reference).
- */
-static
-int type_stack_push(type_stack *stack, struct bt_field_type *type)
-{
- int ret = 0;
- struct type_stack_frame *frame = NULL;
-
- if (!stack || !type) {
- BT_LOGW("Invalid parameter: stack or type is NULL.");
- ret = -1;
- goto end;
- }
-
- frame = g_new0(struct type_stack_frame, 1);
- if (!frame) {
- BT_LOGE_STR("Failed to allocate one field type stack frame.");
- ret = -1;
- goto end;
- }
-
- BT_LOGV("Pushing field type on context's stack: "
- "ft-addr=%p, stack-size-before=%u", type, stack->len);
- frame->type = bt_get(type);
- g_ptr_array_add(stack, frame);
-
-end:
- return ret;
-}
-
-/*
- * Checks whether or not `stack` is empty.
- */
-static
-bt_bool type_stack_empty(type_stack *stack)
-{
- return stack->len == 0;
-}
-
-/*
- * Returns the number of frames in `stack`.
- */
-static
-size_t type_stack_size(type_stack *stack)
-{
- return stack->len;
-}
-
-/*
- * Returns the top frame of `stack`.
- *
- * Return value is owned by `stack`.
- */
-static
-struct type_stack_frame *type_stack_peek(type_stack *stack)
-{
- struct type_stack_frame *entry = NULL;
-
- if (!stack || type_stack_empty(stack)) {
- goto end;
- }
-
- entry = g_ptr_array_index(stack, stack->len - 1);
-end:
- return entry;
-}
-
-/*
- * Returns the frame at index `index` in `stack`.
- *
- * Return value is owned by `stack`.
- */
-static
-struct type_stack_frame *type_stack_at(type_stack *stack,
- size_t index)
-{
- struct type_stack_frame *entry = NULL;
-
- if (!stack || index >= stack->len) {
- goto end;
- }
-
- entry = g_ptr_array_index(stack, index);
-
-end:
- return entry;
-}
-
-/*
- * Removes the top frame of `stack`.
- */
-static
-void type_stack_pop(type_stack *stack)
-{
- if (!type_stack_empty(stack)) {
- /*
- * This will call the frame's destructor and free it, as
- * well as put its contained field type.
- */
- BT_LOGV("Popping context's stack: stack-size-before=%u",
- stack->len);
- g_ptr_array_set_size(stack, stack->len - 1);
- }
-}
-
-/*
- * Returns the scope field type of `scope` in the context `ctx`.
- *
- * Return value is owned by `ctx` on success.
- */
-static
-struct bt_field_type *get_type_from_ctx(struct resolve_context *ctx,
- enum bt_scope scope)
-{
- BT_ASSERT(scope >= BT_SCOPE_TRACE_PACKET_HEADER &&
- scope <= BT_SCOPE_EVENT_FIELDS);
-
- return ctx->scopes[scope - BT_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_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
-{
- enum bt_scope scope;
- enum bt_scope ret = BT_SCOPE_UNKNOWN;
- const size_t prefixes_count = sizeof(absolute_path_prefixes) /
- sizeof(*absolute_path_prefixes);
-
- for (scope = BT_SCOPE_ENV; scope < BT_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_common_scope_string(scope));
- continue;
- }
-
- /* Found it! */
- ret = scope;
- BT_LOGV("Found root scope from absolute path: "
- "path=\"%s\", scope=%s", pathstr,
- bt_common_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_field_path *field_path,
- struct bt_field_type *type, int src_index)
-{
- int ret = 0;
- GList *cur_ptoken = ptokens;
- bt_bool first_level_done = BT_FALSE;
-
- /* Get our own reference */
- bt_get(type);
-
- /* Locate target */
- while (cur_ptoken) {
- int child_index;
- struct bt_field_type *child_type;
- const char *field_name = ptoken_get_string(cur_ptoken);
- enum bt_field_type_id type_id =
- bt_field_type_get_type_id(type);
-
- BT_LOGV("Current path token: token=\"%s\"", field_name);
-
- /* Find to which index corresponds the current path token */
- if (type_id == BT_FIELD_TYPE_ID_ARRAY ||
- type_id == BT_FIELD_TYPE_ID_SEQUENCE) {
- child_index = -1;
- } else {
- child_index = bt_field_type_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_field_type_borrow_field_at_index(type,
- child_index);
- if (!child_type) {
- BT_LOGW("Cannot get child field type: "
- "field-name=\"%s\", src-index=%d, child-index=%d, first-level-done=%d",
- field_name, src_index, child_index, first_level_done);
- ret = -1;
- goto end;
- }
-
- /* Move child type to current type */
- bt_get(child_type);
- BT_MOVE(type, child_type);
- }
-
-end:
- bt_put(type);
- return ret;
-}
-
-/*
- * Converts a known absolute path token list to a field path object
- * within the resolving context `ctx`.
- *
- * `ptokens` is owned by the caller. `field_path` is an output parameter
- * owned by the caller that must be filled here.
- */
-static
-int absolute_ptokens_to_field_path(GList *ptokens,
- struct bt_field_path *field_path,
- struct resolve_context *ctx)
-{
- int ret = 0;
- GList *cur_ptoken;
- struct bt_field_type *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_common_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_field_path *field_path,
- struct resolve_context *ctx)
-{
- int ret = 0;
- int parent_pos_in_stack;
- struct bt_field_path *tail_field_path = bt_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_field_type *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_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_field_type *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_SCOPE_TRACE_PACKET_HEADER) {
- struct bt_field_type *root_type;
- bt_field_path_clear(field_path);
-
- BT_LOGV("Looking into potential root scope: scope=%s",
- bt_common_scope_string(field_path->root));
- root_type = get_type_from_ctx(ctx, field_path->root);
- if (!root_type) {
- field_path->root--;
- continue;
- }
-
- /* Locate target in previous scope */
- ret = ptokens_to_field_path(ptokens, field_path,
- root_type, INT_MAX);
- if (ret) {
- /* Not found yet */
- BT_LOGV_STR("Not found in this scope.");
- field_path->root--;
- continue;
- }
-
- /* Found */
- BT_LOGV_STR("Found in this scope.");
- break;
- }
- }
-
-end:
- BT_PUT(tail_field_path);
- return ret;
-}
-
-/*
- * Converts a path string to a field path object within the resolving
- * context `ctx`.
- *
- * Return value is owned by the caller on success.
- */
-static
-struct bt_field_path *pathstr_to_field_path(const char *pathstr,
- struct resolve_context *ctx)
-{
- int ret;
- enum bt_scope root_scope;
- GList *ptokens = NULL;
- struct bt_field_path *field_path = NULL;
-
- /* Create field path */
- field_path = bt_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_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_common_scope_string(field_path->root));
- ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
- if (ret) {
- BT_LOGW("Cannot get relative field path of path string: "
- "path=\"%s\", start-scope=%s, end-scope=%s",
- pathstr, bt_common_scope_string(ctx->root_scope),
- bt_common_scope_string(field_path->root));
- goto end;
- }
- } else if (root_scope == BT_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_common_scope_string(field_path->root));
- ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
- if (ret) {
- BT_LOGW("Cannot get absolute field path of path string: "
- "path=\"%s\", root-scope=%s",
- pathstr, bt_common_scope_string(root_scope));
- goto end;
- }
- }
-
- if (ret == 0) {
- GString *field_path_pretty =
- bt_field_path_string(field_path);
- const char *field_path_pretty_str =
- field_path_pretty ? field_path_pretty->str : NULL;
-
- BT_LOGV("Found field path: path=\"%s\", field-path=\"%s\"",
- pathstr, field_path_pretty_str);
-
- if (field_path_pretty) {
- g_string_free(field_path_pretty, TRUE);
- }
- }
-
-end:
- if (ret) {
- BT_PUT(field_path);
- }
-
- ptokens_destroy(ptokens);
- return field_path;
-}
-
-/*
- * Retrieves a field type by following the field path `field_path` in
- * the resolving context `ctx`.
- *
- * Return value is owned by the caller on success.
- */
-static
-struct bt_field_type *field_path_to_field_type(
- struct bt_field_path *field_path,
- struct resolve_context *ctx)
-{
- int i;
- struct bt_field_type *type;
-
- /* Start with root type */
- type = get_type_from_ctx(ctx, field_path->root);
- bt_get(type);
- if (!type) {
- /* Error: root type is not available */
- BT_LOGW("Root field type is not available: root-scope=%s",
- bt_common_scope_string(field_path->root));
- goto error;
- }
-
- /* Locate target */
- for (i = 0; i < field_path->indexes->len; i++) {
- struct bt_field_type *child_type;
- int child_index =
- g_array_index(field_path->indexes, int, i);
-
- /* Get child field type */
- child_type = bt_field_type_borrow_field_at_index(type,
- child_index);
- if (!child_type) {
- BT_LOGW("Cannot get field type: "
- "parent-ft-addr=%p, index=%d", type, i);
- goto error;
- }
-
- /* Move child type to current type */
- bt_get(child_type);
- BT_MOVE(type, child_type);
- }
-
- return type;
-
-error:
- BT_PUT(type);
- return type;
-}
-
-/*
- * Returns the equivalent field path object of the context type stack.
- *
- * Return value is owned by the caller on success.
- */
-static
-struct bt_field_path *get_ctx_stack_field_path(struct resolve_context *ctx)
-{
- int i;
- struct bt_field_path *field_path;
-
- /* Create field path */
- field_path = bt_field_path_create();
- if (!field_path) {
- BT_LOGE_STR("Cannot create empty field path.");
- goto error;
- }
-
- field_path->root = ctx->root_scope;
-
- for (i = 0; i < type_stack_size(ctx->type_stack); i++) {
- struct type_stack_frame *frame;
-
- frame = type_stack_at(ctx->type_stack, i);
- g_array_append_val(field_path->indexes, frame->index);
- }
-
- return field_path;
-
-error:
- BT_PUT(field_path);
- return field_path;
-}
-
-/*
- * Returns the lowest common ancestor of two field path objects
- * having the same root scope.
- *
- * `field_path1` and `field_path2` are owned by the caller.
- */
-int get_field_paths_lca_index(struct bt_field_path *field_path1,
- struct bt_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_field_path_string(field_path1);
- GString *field_path2_pretty =
- bt_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_field_path *target_field_path,
- struct bt_field_type *target_type,
- struct resolve_context *ctx)
-{
- int ret = 0;
- struct bt_field_path *ctx_field_path;
- int target_field_path_len = target_field_path->indexes->len;
- int lca_index;
- enum bt_field_type_id ctx_cur_field_type_id;
- enum bt_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_common_scope_string(target_field_path->root),
- bt_common_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_field_type_get_type_id(
- ctx->cur_field_type);
- target_type_id = bt_field_type_get_type_id(target_type);
-
- switch (ctx_cur_field_type_id) {
- case BT_FIELD_TYPE_ID_VARIANT:
- if (target_type_id != BT_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_common_field_type_id_string(target_type_id));
- ret = -1;
- goto end;
- }
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- if (target_type_id != BT_FIELD_TYPE_ID_INTEGER ||
- bt_field_type_integer_is_signed(target_type)) {
- BT_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_common_field_type_id_string(target_type_id));
- ret = -1;
- goto end;
- }
- break;
- default:
- abort();
- }
-
-end:
- BT_PUT(ctx_field_path);
- return ret;
-}
-
-/*
- * Resolves a variant or sequence field type `type`.
- *
- * `type` is owned by the caller.
- */
-static
-int resolve_sequence_or_variant_type(struct bt_field_type *type,
- struct resolve_context *ctx)
-{
- int ret = 0;
- const char *pathstr;
- enum bt_field_type_id type_id = bt_field_type_get_type_id(type);
- struct bt_field_path *target_field_path = NULL;
- struct bt_field_type *target_type = NULL;
- GString *target_field_path_pretty = NULL;
- const char *target_field_path_pretty_str;
-
-
- /* Get path string */
- switch (type_id) {
- case BT_FIELD_TYPE_ID_SEQUENCE:
- pathstr =
- bt_field_type_sequence_get_length_field_name(type);
- break;
- case BT_FIELD_TYPE_ID_VARIANT:
- pathstr =
- bt_field_type_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_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_FIELD_TYPE_ID_SEQUENCE:
- ret = bt_field_type_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_FIELD_TYPE_ID_VARIANT:
- ret = bt_field_type_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_field_type_variant_set_tag_field_type(
- type, target_type);
- if (ret) {
- BT_LOGW("Cannot set varaint field type's tag field type: "
- "ret=%d, ft-addr=%p, path=\"%s\", target-field-path=\"%s\"",
- ret, type, pathstr,
- target_field_path_pretty_str);
- goto end;
- }
- break;
- default:
- abort();
- }
-
-end:
- if (target_field_path_pretty) {
- g_string_free(target_field_path_pretty, TRUE);
- }
-
- BT_PUT(target_field_path);
- BT_PUT(target_type);
- return ret;
-}
-
-/*
- * Resolves a field type `type`.
- *
- * `type` is owned by the caller.
- */
-static
-int resolve_type(struct bt_field_type *type, struct resolve_context *ctx)
-{
- int ret = 0;
- enum bt_field_type_id type_id;
-
- if (!type) {
- /* Type is not available; still valid */
- goto end;
- }
-
- type_id = bt_field_type_get_type_id(type);
- ctx->cur_field_type = type;
-
- /* Resolve sequence/variant field type */
- switch (type_id) {
- case BT_FIELD_TYPE_ID_SEQUENCE:
- case BT_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_FIELD_TYPE_ID_STRUCT:
- case BT_FIELD_TYPE_ID_VARIANT:
- case BT_FIELD_TYPE_ID_SEQUENCE:
- case BT_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_field_type_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_field_type *child_type =
- bt_field_type_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_FIELD_TYPE_ID_ARRAY||
- type_id == BT_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_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_SCOPE_UNKNOWN;
-
- return ret;
-}
-
-BT_HIDDEN
-int bt_resolve_types(
- struct bt_value *environment,
- struct bt_field_type *packet_header_type,
- struct bt_field_type *packet_context_type,
- struct bt_field_type *event_header_type,
- struct bt_field_type *stream_event_ctx_type,
- struct bt_field_type *event_context_type,
- struct bt_field_type *event_payload_type,
- enum bt_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_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_RESOLVE_FLAG_PACKET_HEADER) {
- ret = resolve_root_type(BT_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_RESOLVE_FLAG_PACKET_CONTEXT) {
- ret = resolve_root_type(BT_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_RESOLVE_FLAG_EVENT_HEADER) {
- ret = resolve_root_type(BT_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_RESOLVE_FLAG_STREAM_EVENT_CTX) {
- ret = resolve_root_type(BT_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_RESOLVE_FLAG_EVENT_CONTEXT) {
- ret = resolve_root_type(BT_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_RESOLVE_FLAG_EVENT_PAYLOAD) {
- ret = resolve_root_type(BT_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;
-}
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/fields-internal.h>
#include <babeltrace/ctf-ir/stream-class-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
-#include <babeltrace/ctf-ir/visitor-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ctf-ir/utils-internal.h>
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
+#include <babeltrace/ctf-ir/resolve-field-path-internal.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
#include <babeltrace/endian-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/property-internal.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
-static inline
-int bt_stream_class_initialize(struct bt_stream_class *stream_class,
- const char *name, bt_object_release_func release_func)
-{
- BT_LOGD("Initializing stream class object: name=\"%s\"", name);
-
- bt_object_init_shared_with_parent(&stream_class->base, release_func);
- stream_class->name = g_string_new(name);
- stream_class->event_classes = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_object_try_spec_release);
- if (!stream_class->event_classes) {
- BT_LOGE_STR("Failed to allocate a GPtrArray.");
- goto error;
- }
-
- stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
- g_int64_equal, g_free, NULL);
- if (!stream_class->event_classes_ht) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
- goto error;
- }
-
- BT_LOGD("Initialized stream class object: addr=%p, name=\"%s\"",
- stream_class, name);
- return 0;
-
-error:
- return -1;
-}
+#define BT_ASSERT_PRE_STREAM_CLASS_HOT(_sc) \
+ BT_ASSERT_PRE_HOT((_sc), "Stream class", ": %!+S", (_sc))
static
-void bt_stream_class_destroy(struct bt_object *obj)
+void destroy_stream_class(struct bt_object *obj)
{
struct bt_stream_class *stream_class = (void *) obj;
- BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- bt_put(stream_class->clock_class);
+ BT_LIB_LOGD("Destroying stream class: %!+S", stream_class);
+ BT_LOGD_STR("Putting default clock class.");
+ bt_put(stream_class->default_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);
+ if (stream_class->name.str) {
+ g_string_free(stream_class->name.str, TRUE);
}
BT_LOGD_STR("Putting event header field type.");
- bt_put(stream_class->event_header_field_type);
+ bt_put(stream_class->event_header_ft);
BT_LOGD_STR("Putting packet context field type.");
- bt_put(stream_class->packet_context_field_type);
- BT_LOGD_STR("Putting event context field type.");
- bt_put(stream_class->event_context_field_type);
+ bt_put(stream_class->packet_context_ft);
+ BT_LOGD_STR("Putting event common context field type.");
+ bt_put(stream_class->event_common_context_ft);
bt_object_pool_finalize(&stream_class->event_header_field_pool);
bt_object_pool_finalize(&stream_class->packet_context_field_pool);
g_free(stream_class);
bt_field_wrapper_destroy((void *) field_wrapper);
}
-struct bt_stream_class *bt_stream_class_create(const char *name)
+BT_ASSERT_PRE_FUNC
+static
+bool stream_class_id_is_unique(struct bt_trace *trace, uint64_t id)
+{
+ uint64_t i;
+ bool is_unique = true;
+
+ for (i = 0; i < trace->stream_classes->len; i++) {
+ struct bt_stream_class *sc =
+ trace->stream_classes->pdata[i];
+
+ if (sc->id == id) {
+ is_unique = false;
+ goto end;
+ }
+ }
+
+end:
+ return is_unique;
+}
+
+static
+struct bt_stream_class *create_stream_class_with_id(struct bt_trace *trace,
+ uint64_t id)
{
struct bt_stream_class *stream_class = NULL;
int ret;
- BT_LOGD("Creating stream class object: name=\"%s\"", name);
+ BT_ASSERT(trace);
+ BT_ASSERT_PRE(stream_class_id_is_unique(trace, id),
+ "Duplicate stream class ID: %![trace-]+t, id=%" PRIu64,
+ trace, id);
+ BT_LIB_LOGD("Creating stream class object: %![trace-]+t, id=%" PRIu64,
+ trace, id);
stream_class = g_new0(struct bt_stream_class, 1);
if (!stream_class) {
BT_LOGE_STR("Failed to allocate one stream class.");
goto error;
}
- ret = bt_stream_class_initialize(stream_class, name,
- bt_stream_class_destroy);
- if (ret) {
- /* bt_stream_class_initialize() logs errors */
+ bt_object_init_shared_with_parent(&stream_class->base,
+ destroy_stream_class);
+
+ stream_class->name.str = g_string_new(NULL);
+ if (!stream_class->name.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
+ ret = -1;
+ goto end;
+ }
+
+ stream_class->id = id;
+ stream_class->assigns_automatic_event_class_id = true;
+ stream_class->assigns_automatic_stream_id = true;
+ stream_class->event_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_object_try_spec_release);
+ if (!stream_class->event_classes) {
+ BT_LOGE_STR("Failed to allocate a GPtrArray.");
goto error;
}
goto error;
}
- BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
- stream_class, name);
- return stream_class;
-
-error:
- bt_put(stream_class);
- return NULL;
-}
-
-struct bt_event_header_field *bt_stream_class_create_event_header_field(
- struct bt_stream_class *stream_class)
-{
- struct bt_field_wrapper *field_wrapper;
-
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- BT_ASSERT_PRE(stream_class->frozen,
- "Stream class is not part of a trace: %!+S", stream_class);
- BT_ASSERT_PRE(stream_class->event_header_field_type,
- "Stream class has no event header field type: %!+S",
- stream_class);
- field_wrapper = bt_field_wrapper_create(
- &stream_class->event_header_field_pool,
- (void *) stream_class->event_header_field_type);
- if (!field_wrapper) {
- BT_LIB_LOGE("Cannot allocate one event header field from stream class: "
- "%![sc-]+S", stream_class);
- goto error;
- }
-
- BT_ASSERT(field_wrapper->field);
+ bt_object_set_parent(&stream_class->base, &trace->base);
+ g_ptr_array_add(trace->stream_classes, stream_class);
+ bt_trace_freeze(trace);
+ BT_LIB_LOGD("Created stream class object: %!+S", stream_class);
goto end;
error:
- if (field_wrapper) {
- bt_field_wrapper_destroy(field_wrapper);
- field_wrapper = NULL;
- }
+ BT_PUT(stream_class);
end:
- return (void *) field_wrapper;
+ return stream_class;
}
-struct bt_packet_context_field *bt_stream_class_create_packet_context_field(
- struct bt_stream_class *stream_class)
+struct bt_stream_class *bt_stream_class_create(struct bt_trace *trace)
{
- struct bt_field_wrapper *field_wrapper;
-
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- BT_ASSERT_PRE(stream_class->frozen,
- "Stream class is not part of a trace: %!+S", stream_class);
- BT_ASSERT_PRE(stream_class->packet_context_field_type,
- "Stream class has no packet context field type: %!+S",
- stream_class);
- field_wrapper = bt_field_wrapper_create(
- &stream_class->packet_context_field_pool,
- (void *) stream_class->packet_context_field_type);
- if (!field_wrapper) {
- BT_LIB_LOGE("Cannot allocate one packet context field from stream class: "
- "%![sc-]+S", stream_class);
- goto error;
- }
-
- BT_ASSERT(field_wrapper->field);
- goto end;
-
-error:
- if (field_wrapper) {
- bt_field_wrapper_destroy(field_wrapper);
- field_wrapper = NULL;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE(trace->assigns_automatic_stream_class_id,
+ "Trace does not automatically assigns stream class IDs: "
+ "%![sc-]+t", trace);
+ return create_stream_class_with_id(trace,
+ (uint64_t) trace->stream_classes->len);
+}
-end:
- return (void *) field_wrapper;
+struct bt_stream_class *bt_stream_class_create_with_id(
+ struct bt_trace *trace, uint64_t id)
+{
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE(!trace->assigns_automatic_stream_class_id,
+ "Trace automatically assigns stream class IDs: "
+ "%![sc-]+t", trace);
+ return create_stream_class_with_id(trace, id);
}
struct bt_trace *bt_stream_class_borrow_trace(struct bt_stream_class *stream_class)
{
- BT_ASSERT(stream_class);
- return (void *) bt_object_borrow_parent(&stream_class->base);
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return bt_stream_class_borrow_trace_inline(stream_class);
}
const char *bt_stream_class_get_name(struct bt_stream_class *stream_class)
{
BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- return stream_class->name->len > 0 ? stream_class->name->str : NULL;
+ return stream_class->name.value;
}
int bt_stream_class_set_name(struct bt_stream_class *stream_class,
const char *name)
{
- int ret = 0;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (stream_class->frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- ret = -1;
- goto end;
- }
-
- if (!name) {
- g_string_assign(stream_class->name, "");
- } else {
- if (strlen(name) == 0) {
- BT_LOGW("Invalid parameter: name is empty.");
- ret = -1;
- goto end;
- }
-
- g_string_assign(stream_class->name, name);
- }
-
- BT_LOGV("Set stream class's name: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ g_string_assign(stream_class->name.str, name);
+ stream_class->name.value = stream_class->name.str->str;
+ BT_LIB_LOGV("Set stream class's name: %!+S", stream_class);
+ return 0;
}
-int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
+uint64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
{
- int64_t ret;
-
BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
- if (!stream_class->id_set) {
- BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
- stream_class,
- bt_stream_class_get_name(stream_class));
- ret = (int64_t) -1;
- goto end;
- }
-
- ret = stream_class->id;
-
-end:
- return ret;
+ return stream_class->id;
}
-int bt_stream_class_set_id(struct bt_stream_class *stream_class,
- uint64_t id_param)
+uint64_t bt_stream_class_get_event_class_count(
+ struct bt_stream_class *stream_class)
{
- int ret = 0;
- int64_t id = (int64_t) id_param;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (stream_class->frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- ret = -1;
- goto end;
- }
-
- if (id < 0) {
- BT_LOGW("Invalid parameter: invalid stream class's ID: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", id=%" PRIu64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- id_param);
- ret = -1;
- goto end;
- }
-
- ret = bt_stream_class_set_id_no_check(stream_class, id);
- if (ret == 0) {
- BT_LOGV("Set stream class's ID: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- }
-end:
- return ret;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (uint64_t) stream_class->event_classes->len;
}
-static
-void event_class_exists(gpointer element, gpointer query)
+struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
+ struct bt_stream_class *stream_class, uint64_t index)
{
- struct bt_event_class *event_class_a = element;
- struct search_query *search_query = query;
- struct bt_event_class *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_event_class_get_id(event_class_a);
- id_b = bt_event_class_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_event_class_get_name(event_class_a));
- search_query->found = 1;
- goto end;
- }
-
-end:
- return;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_VALID_INDEX(index, stream_class->event_classes->len);
+ return g_ptr_array_index(stream_class->event_classes, index);
}
-int bt_stream_class_add_event_class(struct bt_stream_class *stream_class,
- struct bt_event_class *event_class)
+struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
+ struct bt_stream_class *trace, uint64_t id)
{
- int ret = 0;
- int64_t *event_id = NULL;
- struct bt_trace *trace = NULL;
- struct bt_stream_class *old_stream_class = NULL;
- struct bt_validation_output validation_output = { 0 };
- struct bt_field_type *packet_header_type = NULL;
- struct bt_field_type *packet_context_type = NULL;
- struct bt_field_type *event_header_type = NULL;
- struct bt_field_type *stream_event_ctx_type = NULL;
- struct bt_field_type *event_context_type = NULL;
- struct bt_field_type *event_payload_type = NULL;
- const enum bt_validation_flag validation_flags =
- BT_VALIDATION_FLAG_EVENT;
- struct bt_clock_class *expected_clock_class = NULL;
-
- if (!stream_class) {
- BT_LOGW("Invalid parameter: stream class is NULL: "
- "stream-class-addr=%p", stream_class);
- ret = -1;
- goto end;
- }
-
- trace = bt_stream_class_borrow_trace(stream_class);
- if (trace && trace->is_static) {
- BT_LOGW("Invalid parameter: stream class's trace is static: "
- "trace-addr=%p, trace-name=\"%s\"",
- trace, bt_trace_get_name(trace));
- ret = -1;
- goto end;
- }
-
- 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_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_class,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- trace = bt_stream_class_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_trace_add_stream_class() or
- * bt_event_create(). This is because the stream class's
- * field types (packet context, event header, event
- * context) could change before the next call to one of
- * those two functions.
- */
- expected_clock_class = bt_get(stream_class->clock_class);
-
- /*
- * At this point, `expected_clock_class` can be NULL,
- * and bt_event_class_validate_single_clock_class()
- * below can set it.
- */
- ret = bt_event_class_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_stream_class_get_id(stream_class),
- bt_stream_class_get_name(stream_class),
- expected_clock_class,
- expected_clock_class ?
- bt_clock_class_get_name(expected_clock_class) :
- NULL);
- goto end;
- }
- }
-
- event_id = g_new(int64_t, 1);
- if (!event_id) {
- BT_LOGE_STR("Failed to allocate one int64_t.");
- ret = -1;
- goto end;
- }
+ struct bt_event_class *event_class = NULL;
+ uint64_t i;
- /* Check for duplicate event classes */
- struct 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;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- old_stream_class = bt_event_class_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_stream_class_get_name(old_stream_class),
- bt_stream_class_get_id(old_stream_class));
- ret = -1;
- goto end;
- }
+ for (i = 0; i < trace->event_classes->len; i++) {
+ struct bt_event_class *event_class_candidate =
+ g_ptr_array_index(trace->event_classes, i);
- 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_trace_borrow_packet_header_field_type(trace);
- packet_context_type =
- bt_stream_class_borrow_packet_context_field_type(
- stream_class);
- event_header_type =
- bt_stream_class_borrow_event_header_field_type(
- stream_class);
- stream_event_ctx_type =
- bt_stream_class_borrow_event_context_field_type(
- stream_class);
- event_context_type =
- bt_event_class_borrow_context_field_type(
- event_class);
- event_payload_type =
- bt_event_class_borrow_payload_field_type(
- event_class);
- ret = bt_validate_class_types(
- trace->environment, packet_header_type,
- packet_context_type, event_header_type,
- stream_event_ctx_type, event_context_type,
- event_payload_type, trace->valid,
- stream_class->valid, event_class->valid,
- &validation_output, validation_flags,
- bt_field_type_copy);
-
- 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);
+ if (event_class_candidate->id == id) {
+ event_class = event_class_candidate;
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_event_class_get_id(event_class);
- if (*event_id < 0) {
- BT_LOGV("Event class has no ID: automatically setting it: "
- "id=%" PRId64, stream_class->next_event_id);
-
- if (bt_event_class_set_id(event_class,
- stream_class->next_event_id)) {
- BT_LOGE("Cannot set event class's ID: id=%" PRId64,
- stream_class->next_event_id);
- ret = -1;
- goto end;
- }
- stream_class->next_event_id++;
- *event_id = stream_class->next_event_id;
- }
-
- bt_object_set_parent(&event_class->base, &stream_class->base);
-
- if (trace) {
- /*
- * At this point we know that the function will be
- * successful. Therefore we can replace the event
- * class's field types with what's in the validation
- * output structure and mark this event class as valid.
- */
- bt_validation_replace_types(NULL, NULL, event_class,
- &validation_output, validation_flags);
- event_class->valid = 1;
-
- /*
- * Put what was not moved in
- * bt_validation_replace_types().
- */
- bt_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_event_class_freeze(event_class);
-
- /*
- * It is safe to set the stream class's unique clock class
- * now if the stream class is frozen.
- */
- if (stream_class->frozen && expected_clock_class) {
- BT_ASSERT(!stream_class->clock_class ||
- stream_class->clock_class == expected_clock_class);
- BT_MOVE(stream_class->clock_class, expected_clock_class);
- }
-
- /* Notifiy listeners of the trace's schema modification. */
- if (trace) {
- struct bt_visitor_object obj = { .object = event_class,
- .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
-
- (void) bt_trace_object_modification(&obj, trace);
- }
-
- BT_LOGD("Added event class to stream class: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", event-class-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_class,
- bt_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
-
-end:
- bt_validation_output_put_types(&validation_output);
- bt_put(expected_clock_class);
- g_free(event_id);
- return ret;
-}
-
-int64_t bt_stream_class_get_event_class_count(
- struct bt_stream_class *stream_class)
-{
- int64_t ret;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = (int64_t) -1;
- goto end;
}
- ret = (int64_t) stream_class->event_classes->len;
end:
- return ret;
-}
-
-struct bt_event_class *bt_stream_class_borrow_event_class_by_index(
- struct bt_stream_class *stream_class, uint64_t index)
-{
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- BT_ASSERT_PRE(index < stream_class->event_classes->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u",
- index, stream_class->event_classes->len);
- return g_ptr_array_index(stream_class->event_classes, index);
-}
-
-struct bt_event_class *bt_stream_class_borrow_event_class_by_id(
- struct bt_stream_class *stream_class, uint64_t id)
-{
- int64_t id_key = (int64_t) id;
-
- BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- BT_ASSERT_PRE(id_key >= 0,
- "Invalid event class ID: %" PRIu64, id);
- return g_hash_table_lookup(stream_class->event_classes_ht,
- &id_key);
+ return event_class;
}
struct bt_field_type *bt_stream_class_borrow_packet_context_field_type(
struct bt_stream_class *stream_class)
{
BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
- return stream_class->packet_context_field_type;
+ return stream_class->packet_context_ft;
}
int bt_stream_class_set_packet_context_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *packet_context_type)
+ struct bt_field_type *field_type)
{
- int ret = 0;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
-
- if (stream_class->frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- ret = -1;
- goto end;
- }
+ int ret;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = NULL,
+ .packet_context = field_type,
+ .event_header = NULL,
+ .event_common_context = NULL,
+ .event_specific_context = NULL,
+ .event_payload = NULL,
+ };
- if (packet_context_type &&
- bt_field_type_get_type_id(packet_context_type) !=
- BT_FIELD_TYPE_ID_STRUCT) {
- /* A packet context must be a structure. */
- BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "packet-context-ft-addr=%p, packet-context-ft-id=%s",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- packet_context_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(packet_context_type)));
- ret = -1;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Packet context field type is not a structure field type: %!+F",
+ field_type);
+ resolve_ctx.packet_header =
+ bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft;
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
goto end;
}
- bt_put(stream_class->packet_context_field_type);
- bt_get(packet_context_type);
- stream_class->packet_context_field_type = packet_context_type;
- BT_LOGV("Set stream class's packet context field type: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "packet-context-ft-addr=%p",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- packet_context_type);
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(stream_class->packet_context_ft);
+ stream_class->packet_context_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set stream class's packet context field type: %!+S",
+ stream_class);
end:
return ret;
struct bt_field_type *bt_stream_class_borrow_event_header_field_type(
struct bt_stream_class *stream_class)
{
- struct bt_field_type *ret = NULL;
-
BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
- if (!stream_class->event_header_field_type) {
- BT_LOGV("Stream class has no event header field type: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- goto end;
- }
-
- ret = stream_class->event_header_field_type;
-
-end:
- return ret;
+ return stream_class->event_header_ft;
}
int bt_stream_class_set_event_header_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *event_header_type)
+ struct bt_field_type *field_type)
{
- int ret = 0;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
+ int ret;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = NULL,
+ .packet_context = NULL,
+ .event_header = field_type,
+ .event_common_context = NULL,
+ .event_specific_context = NULL,
+ .event_payload = NULL,
+ };
- if (stream_class->frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- ret = -1;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Event header field type is not a structure field type: %!+F",
+ field_type);
+ resolve_ctx.packet_header =
+ bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft;
+ resolve_ctx.packet_context = stream_class->packet_context_ft;
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
goto end;
}
- if (event_header_type &&
- bt_field_type_get_type_id(event_header_type) !=
- BT_FIELD_TYPE_ID_STRUCT) {
- /* An event header must be a structure. */
- BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "event-header-ft-addr=%p, event-header-ft-id=%s",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_header_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(event_header_type)));
- ret = -1;
- goto end;
- }
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(stream_class->event_header_ft);
+ stream_class->event_header_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set stream class's event header field type: %!+S",
+ stream_class);
- bt_put(stream_class->event_header_field_type);
- stream_class->event_header_field_type = bt_get(event_header_type);
- BT_LOGV("Set stream class's event header field type: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "event-header-ft-addr=%p",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_header_type);
end:
return ret;
}
-struct bt_field_type *bt_stream_class_borrow_event_context_field_type(
+struct bt_field_type *bt_stream_class_borrow_event_common_context_field_type(
struct bt_stream_class *stream_class)
{
- struct bt_field_type *ret = NULL;
-
BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
- if (!stream_class->event_context_field_type) {
- goto end;
- }
-
- ret = stream_class->event_context_field_type;
-
-end:
- return ret;
+ return stream_class->event_common_context_ft;
}
-int bt_stream_class_set_event_context_field_type(
+int bt_stream_class_set_event_common_context_field_type(
struct bt_stream_class *stream_class,
- struct bt_field_type *event_context_type)
+ struct bt_field_type *field_type)
{
- int ret = 0;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- ret = -1;
- goto end;
- }
+ int ret;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = NULL,
+ .packet_context = NULL,
+ .event_header = NULL,
+ .event_common_context = field_type,
+ .event_specific_context = NULL,
+ .event_payload = NULL,
+ };
- if (stream_class->frozen) {
- BT_LOGW("Invalid parameter: stream class is frozen: "
- "addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- ret = -1;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Event common context field type is not a structure field type: %!+F",
+ field_type);
+ resolve_ctx.packet_header =
+ bt_stream_class_borrow_trace_inline(stream_class)->packet_header_ft;
+ resolve_ctx.packet_context = stream_class->packet_context_ft;
+ resolve_ctx.event_header = stream_class->event_header_ft;
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
goto end;
}
- if (event_context_type &&
- bt_field_type_get_type_id(event_context_type) !=
- BT_FIELD_TYPE_ID_STRUCT) {
- /* A packet context must be a structure. */
- BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "event-context-ft-addr=%p, event-context-ft-id=%s",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_context_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(event_context_type)));
- ret = -1;
- goto end;
- }
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(stream_class->event_common_context_ft);
+ stream_class->event_common_context_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set stream class's event common context field type: %!+S",
+ stream_class);
- bt_put(stream_class->event_context_field_type);
- stream_class->event_context_field_type = bt_get(event_context_type);
- BT_LOGV("Set stream class's event context field type: "
- "addr=%p, name=\"%s\", id=%" PRId64 ", "
- "event-context-ft-addr=%p",
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_context_type);
end:
return ret;
}
-static
-int64_t get_event_class_count(void *element)
+BT_HIDDEN
+void _bt_stream_class_freeze(struct bt_stream_class *stream_class)
{
- return bt_stream_class_get_event_class_count(
- (struct bt_stream_class *) element);
+ /* The field types and default clock class are already frozen */
+ BT_ASSERT(stream_class);
+ BT_LIB_LOGD("Freezing stream class: %!+S", stream_class);
+ stream_class->frozen = true;
}
-static
-void *get_event_class(void *element, int i)
+int bt_stream_class_set_default_clock_class(
+ struct bt_stream_class *stream_class,
+ struct bt_clock_class *clock_class)
{
- return bt_stream_class_get_event_class_by_index(
- (struct bt_stream_class *) element, i);
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ bt_put(stream_class->default_clock_class);
+ stream_class->default_clock_class = bt_get(clock_class);
+ bt_clock_class_freeze(clock_class);
+ BT_LIB_LOGV("Set stream class's default clock class: %!+S",
+ stream_class);
+ return 0;
}
-static
-int visit_event_class(void *object, bt_visitor visitor,void *data)
+struct bt_clock_class *bt_stream_class_borrow_default_clock_class(
+ struct bt_stream_class *stream_class)
{
- struct bt_visitor_object obj = {
- .object = object,
- .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
- };
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return stream_class->default_clock_class;
+}
- return visitor(&obj, data);
+bt_bool bt_stream_class_assigns_automatic_event_class_id(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->assigns_automatic_event_class_id;
}
-BT_HIDDEN
-int bt_stream_class_visit(struct bt_stream_class *stream_class,
- bt_visitor visitor, void *data)
+int bt_stream_class_set_assigns_automatic_event_class_id(
+ struct bt_stream_class *stream_class, bt_bool value)
{
- int ret;
- struct bt_visitor_object obj = {
- .object = stream_class,
- .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
- };
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ stream_class->assigns_automatic_event_class_id = (bool) value;
+ BT_LIB_LOGV("Set stream class's automatic event class ID "
+ "assignment property: %!+S", stream_class);
+ return 0;
+}
- 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;
- }
+bt_bool bt_stream_class_assigns_automatic_stream_id(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->assigns_automatic_stream_id;
+}
- ret = visitor_helper(&obj, get_event_class_count,
- get_event_class,
- visit_event_class, visitor, data);
- BT_LOGV("visitor_helper() returned: ret=%d", ret);
+int bt_stream_class_set_assigns_automatic_stream_id(
+ struct bt_stream_class *stream_class, bt_bool value)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ stream_class->assigns_automatic_stream_id = (bool) value;
+ BT_LIB_LOGV("Set stream class's automatic stream ID "
+ "assignment property: %!+S", stream_class);
+ return 0;
+}
-end:
- return ret;
+bt_bool bt_stream_class_packets_have_discarded_event_counter_snapshot(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->packets_have_discarded_event_counter_snapshot;
}
-BT_HIDDEN
-void bt_stream_class_freeze(struct bt_stream_class *stream_class)
+int bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
+ struct bt_stream_class *stream_class, bt_bool value)
{
- if (!stream_class || stream_class->frozen) {
- return;
- }
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ stream_class->packets_have_discarded_event_counter_snapshot =
+ (bool) value;
+ BT_LIB_LOGV("Set stream class's "
+ "\"packets have discarded event counter snapshot\" property: "
+ "%!+S", stream_class);
+ return 0;
+}
- BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
- stream_class->frozen = 1;
- bt_field_type_freeze(stream_class->event_header_field_type);
- bt_field_type_freeze(stream_class->packet_context_field_type);
- bt_field_type_freeze(stream_class->event_context_field_type);
- bt_clock_class_freeze(stream_class->clock_class);
+bt_bool bt_stream_class_packets_have_packet_counter_snapshot(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->packets_have_packet_counter_snapshot;
}
-BT_HIDDEN
-int bt_stream_class_validate_single_clock_class(
- struct bt_stream_class *stream_class,
- struct bt_clock_class **expected_clock_class)
+int bt_stream_class_set_packets_have_packet_counter_snapshot(
+ struct bt_stream_class *stream_class, bt_bool value)
{
- int ret;
- uint64_t i;
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ stream_class->packets_have_packet_counter_snapshot =
+ (bool) value;
+ BT_LIB_LOGV("Set stream class's "
+ "\"packets have packet counter snapshot\" property: "
+ "%!+S", stream_class);
+ return 0;
+}
- BT_ASSERT(stream_class);
- BT_ASSERT(expected_clock_class);
- ret = bt_field_type_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_stream_class_get_name(stream_class),
- stream_class->id,
- stream_class->packet_context_field_type);
- goto end;
- }
+bt_bool bt_stream_class_packets_have_default_beginning_clock_value(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->packets_have_default_beginning_cv;
+}
- ret = bt_field_type_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_stream_class_get_name(stream_class),
- stream_class->id,
- stream_class->event_header_field_type);
- goto end;
- }
+int bt_stream_class_set_packets_have_default_beginning_clock_value(
+ struct bt_stream_class *stream_class, bt_bool value)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ BT_ASSERT_PRE(!value || stream_class->default_clock_class,
+ "Stream class does not have a default clock class: %!+S",
+ stream_class);
+ stream_class->packets_have_default_beginning_cv = (bool) value;
+ BT_LIB_LOGV("Set stream class's "
+ "\"packets have default beginning clock value\" property: "
+ "%!+S", stream_class);
+ return 0;
+}
- ret = bt_field_type_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_stream_class_get_name(stream_class),
- stream_class->id,
- stream_class->event_context_field_type);
- goto end;
- }
+bt_bool bt_stream_class_packets_have_default_end_clock_value(
+ struct bt_stream_class *stream_class)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ return (bt_bool) stream_class->packets_have_default_end_cv;
+}
- for (i = 0; i < stream_class->event_classes->len; i++) {
- struct bt_event_class *event_class =
- g_ptr_array_index(stream_class->event_classes, i);
-
- BT_ASSERT(event_class);
- ret = bt_event_class_validate_single_clock_class(
- event_class, expected_clock_class);
- 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_stream_class_get_name(stream_class),
- stream_class->id);
- goto end;
- }
- }
+int bt_stream_class_set_packets_have_default_end_clock_value(
+ struct bt_stream_class *stream_class, bt_bool value)
+{
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE_STREAM_CLASS_HOT(stream_class);
+ BT_ASSERT_PRE(!value || stream_class->default_clock_class,
+ "Stream class does not have a default clock class: %!+S",
+ stream_class);
+ stream_class->packets_have_default_end_cv = (bool) value;
+ BT_LIB_LOGV("Set stream class's "
+ "\"packets have default end clock value\" property: "
+ "%!+S", stream_class);
+ return 0;
+}
-end:
- return ret;
+bt_bool bt_stream_class_default_clock_is_always_known(
+ struct bt_stream_class *stream_class)
+{
+ /* BT_CLOCK_VALUE_STATUS_UNKNOWN is not supported as of 2.0 */
+ return BT_TRUE;
}
#include <babeltrace/compiler-internal.h>
#include <babeltrace/align-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/property-internal.h>
#include <inttypes.h>
#include <unistd.h>
-static inline
-void bt_stream_finalize(struct bt_stream *stream)
-{
- BT_LOGD("Finalizing stream object: addr=%p, name=\"%s\"",
- stream, bt_stream_get_name(stream));
-
- if (stream->name) {
- g_string_free(stream->name, TRUE);
- }
-}
+#define BT_ASSERT_PRE_STREAM_HOT(_stream) \
+ BT_ASSERT_PRE_HOT((_stream), "Stream", ": %!+s", (_stream))
static
-void bt_stream_destroy(struct bt_object *obj)
+void destroy_stream(struct bt_object *obj)
{
struct bt_stream *stream = (void *) obj;
- BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
- stream, bt_stream_get_name(stream));
+ BT_LIB_LOGD("Destroying stream object: %!+s", stream);
+
+ if (stream->name.str) {
+ g_string_free(stream->name.str, TRUE);
+ }
+
bt_object_pool_finalize(&stream->packet_pool);
- bt_stream_finalize((void *) obj);
g_free(stream);
}
-static inline
-int bt_stream_initialize(
- struct bt_stream *stream,
- struct bt_stream_class *stream_class, const char *name,
- uint64_t id, bt_object_release_func release_func)
+static
+void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream)
{
- int ret = 0;
- struct bt_trace *trace = NULL;
-
- bt_object_init_shared_with_parent(&stream->base, release_func);
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto error;
- }
-
- BT_LOGD("Initializing stream object: stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-name=\"%s\", "
- "stream-id=%" PRIu64,
- stream_class, bt_stream_class_get_name(stream_class),
- name, id);
- trace = bt_stream_class_borrow_trace(stream_class);
- if (!trace) {
- BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-name=\"%s\"",
- stream_class,
- bt_stream_class_get_name(stream_class), name);
- goto error;
- }
-
- if (id != -1ULL) {
- /*
- * Validate that the given ID is unique amongst all the
- * existing trace's streams created from the same stream
- * class.
- */
- size_t i;
+ bt_packet_destroy(packet);
+}
- for (i = 0; i < trace->streams->len; i++) {
- struct bt_stream *trace_stream =
- g_ptr_array_index(trace->streams, i);
+BT_ASSERT_PRE_FUNC
+static inline
+bool stream_id_is_unique(struct bt_trace *trace,
+ struct bt_stream_class *stream_class, uint64_t id)
+{
+ uint64_t i;
+ bool is_unique = true;
- if (trace_stream->stream_class != (void *) stream_class) {
- continue;
- }
+ for (i = 0; i < trace->streams->len; i++) {
+ struct bt_stream *stream = trace->streams->pdata[i];
- if (trace_stream->id == id) {
- BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID.");
- goto error;
- }
+ if (stream->class != stream_class) {
+ continue;
}
- }
- /*
- * Acquire reference to parent since stream will become publicly
- * reachable; it needs its parent to remain valid.
- */
- bt_object_set_parent(&stream->base, &trace->base);
- stream->stream_class = stream_class;
- stream->id = (int64_t) id;
-
- if (name) {
- stream->name = g_string_new(name);
- if (!stream->name) {
- BT_LOGE_STR("Failed to allocate a GString.");
- goto error;
+ if (stream->id == id) {
+ is_unique = false;
+ goto end;
}
}
- BT_LOGD("Set stream's trace parent: trace-addr=%p", trace);
-
- /* Add this stream to the trace's streams */
- BT_LOGD("Created stream object: addr=%p", stream);
- goto end;
-
-error:
- ret = -1;
-
end:
- return ret;
-}
-
-static
-void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream)
-{
- bt_packet_destroy(packet);
+ return is_unique;
}
static
-struct bt_stream *bt_stream_create_with_id_no_check(
- struct bt_stream_class *stream_class,
- const char *name, uint64_t id)
+struct bt_stream *create_stream_with_id(struct bt_stream_class *stream_class,
+ uint64_t id)
{
int ret;
- struct bt_stream *stream = NULL;
- struct bt_trace *trace = NULL;
-
- BT_LOGD("Creating stream object: stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-name=\"%s\", "
- "stream-id=%" PRIu64,
- stream_class, bt_stream_class_get_name(stream_class),
- name, id);
-
- trace = bt_stream_class_borrow_trace(stream_class);
- if (!trace) {
- BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-name=\"%s\"",
- stream_class, bt_stream_class_get_name(stream_class),
- name);
- goto error;
- }
-
- if (bt_trace_is_static(trace)) {
- /*
- * A static trace has the property that all its stream
- * classes, clock classes, and streams are definitive:
- * no more can be added, and each object is also frozen.
- */
- BT_LOGW("Invalid parameter: cannot create stream from a stream class which is part of a static trace: "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-name=\"%s\", trace-addr=%p",
- stream_class, bt_stream_class_get_name(stream_class),
- name, trace);
- goto error;
- }
-
+ struct bt_stream *stream;
+ struct bt_trace *trace;
+
+ BT_ASSERT(stream_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
+ BT_ASSERT_PRE(stream_id_is_unique(trace, stream_class, id),
+ "Duplicate stream ID: %![trace-]+t, id=%" PRIu64, trace, id);
+ BT_ASSERT_PRE(!trace->is_static,
+ "Trace is static: %![trace-]+t", trace);
+ BT_LIB_LOGD("Creating stream object: %![trace-]+t, id=%" PRIu64,
+ trace, id);
stream = g_new0(struct bt_stream, 1);
if (!stream) {
BT_LOGE_STR("Failed to allocate one stream.");
goto error;
}
- ret = bt_stream_initialize(stream, stream_class, name,
- id, bt_stream_destroy);
- if (ret) {
- /* bt_stream_initialize() logs errors */
+ bt_object_init_shared_with_parent(&stream->base, destroy_stream);
+ stream->name.str = g_string_new(NULL);
+ if (!stream->name.str) {
+ BT_LOGE_STR("Failed to allocate a GString.");
goto error;
}
+ stream->id = id;
ret = bt_object_pool_initialize(&stream->packet_pool,
(bt_object_pool_new_object_func) bt_packet_new,
(bt_object_pool_destroy_object_func) bt_stream_free_packet,
goto error;
}
- g_ptr_array_add(trace->streams, stream);
- BT_LOGD("Created stream object: addr=%p", stream);
+ stream->class = stream_class;
+ bt_trace_add_stream(trace, stream);
+ bt_stream_class_freeze(stream_class);
+ BT_LIB_LOGD("Created stream object: %!+s", stream);
goto end;
error:
return stream;
}
-struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
- const char *name, uint64_t id_param)
+struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class)
{
- struct bt_stream *stream = NULL;
- int64_t id = (int64_t) id_param;
-
- if (!stream_class) {
- BT_LOGW_STR("Invalid parameter: stream class is NULL.");
- goto end;
- }
-
- if (id < 0) {
- BT_LOGW("Invalid parameter: invalid stream's ID: "
- "name=\"%s\", id=%" PRIu64,
- name, id_param);
- goto end;
- }
-
- stream = bt_stream_create_with_id_no_check(stream_class,
- name, id_param);
+ uint64_t id;
+
+ BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+ BT_ASSERT_PRE(stream_class->assigns_automatic_stream_id,
+ "Stream class does not automatically assigns stream IDs: "
+ "%![sc-]+S", stream_class);
+ id = bt_trace_get_automatic_stream_id(
+ bt_stream_class_borrow_trace_inline(stream_class),
+ stream_class);
+ return create_stream_with_id(stream_class, id);
+}
-end:
- return stream;
+struct bt_stream *bt_stream_create_with_id(struct bt_stream_class *stream_class,
+ uint64_t id)
+{
+ BT_ASSERT_PRE(!stream_class->assigns_automatic_stream_id,
+ "Stream class automatically assigns stream IDs: "
+ "%![sc-]+S", stream_class);
+ return create_stream_with_id(stream_class, id);
}
struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream)
{
- BT_ASSERT(stream);
- return stream->stream_class;
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+ return stream->class;
}
const char *bt_stream_get_name(struct bt_stream *stream)
{
- BT_ASSERT_PRE_NON_NULL(stream, "Stream");
- return stream->name ? stream->name->str : NULL;
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream class");
+ return stream->name.value;
}
-int64_t bt_stream_get_id(struct bt_stream *stream)
+int bt_stream_set_name(struct bt_stream *stream, const char *name)
{
- int64_t ret;
+ BT_ASSERT_PRE_NON_NULL(stream, "Clock class");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_STREAM_HOT(stream);
+ g_string_assign(stream->name.str, name);
+ stream->name.value = stream->name.str->str;
+ BT_LIB_LOGV("Set stream class's name: %!+S", stream);
+ return 0;
+}
- BT_ASSERT_PRE_NON_NULL(stream, "Stream");
- ret = stream->id;
- if (ret < 0) {
- BT_LOGV("Stream's ID is not set: addr=%p, name=\"%s\"",
- stream, bt_stream_get_name(stream));
- }
+uint64_t bt_stream_get_id(struct bt_stream *stream)
+{
+ BT_ASSERT_PRE_NON_NULL(stream, "Stream class");
+ return stream->id;
+}
- return ret;
+BT_HIDDEN
+void _bt_stream_freeze(struct bt_stream *stream)
+{
+ /* The field types and default clock class are already frozen */
+ BT_ASSERT(stream);
+ BT_LIB_LOGD("Freezing stream: %!+s", stream);
+ stream->frozen = true;
}
#include <babeltrace/ctf-ir/field-wrapper-internal.h>
#include <babeltrace/ctf-ir/field-types-internal.h>
#include <babeltrace/ctf-ir/attributes-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
-#include <babeltrace/ctf-ir/visitor-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/resolve-field-path-internal.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/values.h>
#include <babeltrace/values-internal.h>
#include <babeltrace/types.h>
#include <babeltrace/endian-internal.h>
#include <babeltrace/assert-internal.h>
+#include <babeltrace/compat/glib-internal.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
-#define DEFAULT_IDENTIFIER_SIZE 128
-#define DEFAULT_METADATA_STRING_SIZE 4096
-
-struct listener_wrapper {
- bt_listener_cb listener;
- void *data;
-};
-
struct bt_trace_is_static_listener_elem {
bt_trace_is_static_listener func;
bt_trace_listener_removed removed;
void *data;
};
-static inline
-void bt_trace_finalize(struct bt_trace *trace)
-{
- BT_LOGD("Finalizing trace object: addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
-
- if (trace->environment) {
- BT_LOGD_STR("Destroying environment attributes.");
- bt_attributes_destroy(trace->environment);
- }
-
- if (trace->name) {
- g_string_free(trace->name, TRUE);
- }
-
- if (trace->clock_classes) {
- BT_LOGD_STR("Putting clock classes.");
- g_ptr_array_free(trace->clock_classes, TRUE);
- }
-
- if (trace->streams) {
- BT_LOGD_STR("Destroying streams.");
- g_ptr_array_free(trace->streams, TRUE);
- }
-
- if (trace->stream_classes) {
- BT_LOGD_STR("Destroying stream classes.");
- g_ptr_array_free(trace->stream_classes, TRUE);
- }
-
- BT_LOGD_STR("Putting packet header field type.");
- bt_put(trace->packet_header_field_type);
-}
+#define BT_ASSERT_PRE_TRACE_HOT(_trace) \
+ BT_ASSERT_PRE_HOT((_trace), "Trace", ": %!+t", (_trace))
static
-void bt_trace_destroy(struct bt_object *obj)
+void destroy_trace(struct bt_object *obj)
{
struct bt_trace *trace = (void *) obj;
- BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
+ BT_LIB_LOGD("Destroying trace object: %!+t", trace);
/*
* Call remove listeners first so that everything else still
g_array_free(trace->is_static_listeners, TRUE);
}
- if (trace->listeners) {
- g_ptr_array_free(trace->listeners, TRUE);
- }
-
bt_object_pool_finalize(&trace->packet_header_field_pool);
- bt_trace_finalize(trace);
- g_free(trace);
-}
-static inline
-int bt_trace_initialize(struct bt_trace *trace,
- bt_object_release_func release_func)
-{
- int ret = 0;
-
- BT_LOGD_STR("Initializing trace object.");
- trace->native_byte_order = BT_BYTE_ORDER_UNSPECIFIED;
- bt_object_init_shared_with_parent(&trace->base, release_func);
- trace->clock_classes = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_put);
- if (!trace->clock_classes) {
- BT_LOGE_STR("Failed to allocate one GPtrArray.");
- goto error;
+ if (trace->environment) {
+ BT_LOGD_STR("Destroying environment attributes.");
+ bt_attributes_destroy(trace->environment);
}
- trace->streams = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_object_try_spec_release);
- if (!trace->streams) {
- BT_LOGE_STR("Failed to allocate one GPtrArray.");
- goto error;
+ if (trace->name.str) {
+ g_string_free(trace->name.str, TRUE);
}
- trace->stream_classes = g_ptr_array_new_with_free_func(
- (GDestroyNotify) bt_object_try_spec_release);
- if (!trace->stream_classes) {
- BT_LOGE_STR("Failed to allocate one GPtrArray.");
- goto error;
+ if (trace->streams) {
+ BT_LOGD_STR("Destroying streams.");
+ g_ptr_array_free(trace->streams, TRUE);
}
- /* Create the environment array object */
- trace->environment = bt_attributes_create();
- if (!trace->environment) {
- BT_LOGE_STR("Cannot create empty attributes object.");
- goto error;
+ if (trace->stream_classes) {
+ BT_LOGD_STR("Destroying stream classes.");
+ g_ptr_array_free(trace->stream_classes, TRUE);
}
- BT_LOGD("Initialized trace object: addr=%p", trace);
- goto end;
-
-error:
- ret = -1;
+ if (trace->stream_classes_stream_count) {
+ g_hash_table_destroy(trace->stream_classes_stream_count);
+ }
-end:
- return ret;
+ BT_LOGD_STR("Putting packet header field type.");
+ bt_put(trace->packet_header_ft);
+ g_free(trace);
}
static
struct bt_trace *trace = NULL;
int ret;
- BT_LOGD_STR("Creating trace object.");
+ BT_LOGD_STR("Creating default trace object.");
trace = g_new0(struct bt_trace, 1);
if (!trace) {
BT_LOGE_STR("Failed to allocate one trace.");
goto error;
}
- ret = bt_trace_initialize(trace, bt_trace_destroy);
- if (ret) {
- /* bt_trace_initialize() logs errors */
+ bt_object_init_shared_with_parent(&trace->base, destroy_trace);
+ trace->streams = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_object_try_spec_release);
+ if (!trace->streams) {
+ BT_LOGE_STR("Failed to allocate one GPtrArray.");
goto error;
}
- trace->listeners = g_ptr_array_new_with_free_func(
- (GDestroyNotify) g_free);
- if (!trace->listeners) {
+ trace->stream_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_object_try_spec_release);
+ if (!trace->stream_classes) {
BT_LOGE_STR("Failed to allocate one GPtrArray.");
goto error;
}
+ trace->stream_classes_stream_count = g_hash_table_new(g_direct_hash,
+ g_direct_equal);
+ if (!trace->stream_classes_stream_count) {
+ BT_LOGE_STR("Failed to allocate one GHashTable.");
+ goto error;
+ }
+
+ trace->name.str = g_string_new(NULL);
+ if (!trace->name.str) {
+ BT_LOGE_STR("Failed to allocate one GString.");
+ goto error;
+ }
+
+ trace->environment = bt_attributes_create();
+ if (!trace->environment) {
+ BT_LOGE_STR("Cannot create empty attributes object.");
+ goto error;
+ }
+
trace->is_static_listeners = g_array_new(FALSE, TRUE,
sizeof(struct bt_trace_is_static_listener_elem));
if (!trace->is_static_listeners) {
goto error;
}
+ trace->assigns_automatic_stream_class_id = true;
ret = bt_object_pool_initialize(&trace->packet_header_field_pool,
(bt_object_pool_new_object_func) bt_field_wrapper_new,
(bt_object_pool_destroy_object_func) free_packet_header_field,
goto error;
}
- BT_LOGD("Created trace object: addr=%p", trace);
- return trace;
+ BT_LIB_LOGD("Created trace object: %!+t", trace);
+ goto end;
error:
BT_PUT(trace);
+
+end:
return trace;
}
const char *bt_trace_get_name(struct bt_trace *trace)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->name ? trace->name->str : NULL;
+ return trace->name.value;
}
int bt_trace_set_name(struct bt_trace *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_trace_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_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_TRACE_HOT(trace);
+ g_string_assign(trace->name.str, name);
+ trace->name.value = trace->name.str->str;
+ BT_LIB_LOGV("Set trace's name: %!+t", trace);
+ return 0;
}
-const unsigned char *bt_trace_get_uuid(struct bt_trace *trace)
+bt_uuid bt_trace_get_uuid(struct bt_trace *trace)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->uuid_set ? trace->uuid : NULL;
+ return trace->uuid.value;
}
-int bt_trace_set_uuid(struct bt_trace *trace,
- const unsigned char *uuid)
+int bt_trace_set_uuid(struct bt_trace *trace, bt_uuid 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_trace_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_trace_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_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(uuid, "UUID");
+ BT_ASSERT_PRE_TRACE_HOT(trace);
+ memcpy(trace->uuid.uuid, uuid, BABELTRACE_UUID_LEN);
+ trace->uuid.value = trace->uuid.uuid;
+ BT_LIB_LOGV("Set trace's UUID: %!+t", trace);
+ return 0;
}
-int bt_trace_set_environment_field(struct bt_trace *trace,
- const char *name, struct bt_value *value)
+BT_ASSERT_FUNC
+static
+bool trace_has_environment_entry(struct bt_trace *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;
- }
+ struct bt_value *attribute;
- if (!value) {
- BT_LOGW_STR("Invalid parameter: value is NULL.");
- ret = -1;
- goto end;
- }
-
- if (trace->is_static) {
- BT_LOGW("Invalid parameter: trace is static: "
- "addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
- ret = -1;
- goto end;
- }
-
- if (!bt_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_trace_get_name(trace), name);
- ret = -1;
- goto end;
- }
-
- if (!bt_value_is_integer(value) && !bt_value_is_string(value)) {
- BT_LOGW("Invalid parameter: environment field's value is not an integer or string value: "
- "trace-addr=%p, trace-name=\"%s\", "
- "env-name=\"%s\", env-value-type=%s",
- trace, bt_trace_get_name(trace), name,
- bt_value_type_string(bt_value_get_type(value)));
- ret = -1;
- goto end;
- }
+ BT_ASSERT(trace);
- if (trace->frozen) {
- /*
- * New environment fields may be added to a frozen trace,
- * but existing fields may not be changed.
- *
- * The object passed is frozen like all other attributes.
- */
- struct bt_value *attribute =
- bt_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_trace_get_name(trace), name);
- ret = -1;
- goto end;
- }
+ attribute = bt_attributes_borrow_field_value_by_name(
+ trace->environment, name);
+ return attribute != NULL;
+}
- bt_value_freeze(value);
- }
+static
+int set_environment_entry(struct bt_trace *trace, const char *name,
+ struct bt_value *value)
+{
+ int ret;
+ BT_ASSERT(trace);
+ BT_ASSERT(name);
+ BT_ASSERT(value);
+ BT_ASSERT_PRE(!trace->frozen ||
+ !trace_has_environment_entry(trace, name),
+ "Trace is frozen: cannot replace environment entry: "
+ "%![trace-]+t, entry-name=\"%s\"", trace, name);
ret = bt_attributes_set_field_value(trace->environment, name,
value);
+ bt_value_freeze(value);
if (ret) {
- BT_LOGE("Cannot set environment field's value: "
- "trace-addr=%p, trace-name=\"%s\", "
- "env-name=\"%s\"",
- trace, bt_trace_get_name(trace), name);
+ BT_LIB_LOGE("Cannot set trace's environment entry: "
+ "%![trace-]+t, entry-name=\"%s\"", trace, name);
} else {
- BT_LOGV("Set environment field's value: "
- "trace-addr=%p, trace-name=\"%s\", "
- "env-name=\"%s\", value-addr=%p",
- trace, bt_trace_get_name(trace), name, value);
+ BT_LIB_LOGV("Set trace's environment entry: "
+ "%![trace-]+t, entry-name=\"%s\"", trace, name);
}
-end:
return ret;
}
-int bt_trace_set_environment_field_string(struct bt_trace *trace,
+int bt_trace_set_environment_entry_string(struct bt_trace *trace,
const char *name, const char *value)
{
- int ret = 0;
- struct bt_value *env_value_string_obj = NULL;
-
- if (!value) {
- BT_LOGW_STR("Invalid parameter: value is NULL.");
- ret = -1;
- goto end;
- }
+ int ret;
+ struct bt_value *value_obj;
- env_value_string_obj = bt_value_string_create_init(value);
- if (!env_value_string_obj) {
- BT_LOGE_STR("Cannot create string value object.");
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ value_obj = bt_value_string_create_init(value);
+ if (!value_obj) {
+ BT_LOGE_STR("Cannot create a string value object.");
ret = -1;
goto end;
}
- /* bt_trace_set_environment_field() logs errors */
- ret = bt_trace_set_environment_field(trace, name,
- env_value_string_obj);
+ /* set_environment_entry() logs errors */
+ ret = set_environment_entry(trace, name, value_obj);
end:
- bt_put(env_value_string_obj);
+ bt_put(value_obj);
return ret;
}
-int bt_trace_set_environment_field_integer(
+int bt_trace_set_environment_entry_integer(
struct bt_trace *trace, const char *name, int64_t value)
{
- int ret = 0;
- struct bt_value *env_value_integer_obj = NULL;
+ int ret;
+ struct bt_value *value_obj;
- env_value_integer_obj = bt_value_integer_create_init(value);
- if (!env_value_integer_obj) {
- BT_LOGE_STR("Cannot create integer value object.");
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ value_obj = bt_value_integer_create_init(value);
+ if (!value_obj) {
+ BT_LOGE_STR("Cannot create an integer value object.");
ret = -1;
goto end;
}
- /* bt_trace_set_environment_field() logs errors */
- ret = bt_trace_set_environment_field(trace, name,
- env_value_integer_obj);
+ /* set_environment_entry() logs errors */
+ ret = set_environment_entry(trace, name, value_obj);
end:
- bt_put(env_value_integer_obj);
+ bt_put(value_obj);
return ret;
}
-int64_t bt_trace_get_environment_field_count(struct bt_trace *trace)
+uint64_t bt_trace_get_environment_entry_count(struct bt_trace *trace)
{
int64_t ret;
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
ret = bt_attributes_get_count(trace->environment);
BT_ASSERT(ret >= 0);
- return ret;
-}
-
-const char *
-bt_trace_get_environment_field_name_by_index(struct bt_trace *trace,
- uint64_t index)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return bt_attributes_get_field_name(trace->environment, index);
+ return (uint64_t) ret;
}
-struct bt_value *bt_trace_borrow_environment_field_value_by_index(
- struct bt_trace *trace, uint64_t index)
+void bt_trace_borrow_environment_entry_by_index(
+ struct bt_trace *trace, uint64_t index,
+ const char **name, struct bt_value **value)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return bt_attributes_borrow_field_value(trace->environment, index);
+ BT_ASSERT_PRE_NON_NULL(name, "Name");
+ BT_ASSERT_PRE_NON_NULL(value, "Value");
+ BT_ASSERT_PRE_VALID_INDEX(index,
+ bt_attributes_get_count(trace->environment));
+ *value = bt_attributes_borrow_field_value(trace->environment, index);
+ BT_ASSERT(*value);
+ *name = bt_attributes_get_field_name(trace->environment, index);
+ BT_ASSERT(*name);
}
-struct bt_value *bt_trace_borrow_environment_field_value_by_name(
+struct bt_value *bt_trace_borrow_environment_entry_value_by_name(
struct bt_trace *trace, const char *name)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
name);
}
-int bt_trace_add_clock_class(struct bt_trace *trace,
- struct bt_clock_class *clock_class)
+uint64_t bt_trace_get_stream_count(struct bt_trace *trace)
{
- int ret = 0;
-
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- ret = -1;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ return (uint64_t) trace->streams->len;
+}
- if (trace->is_static) {
- BT_LOGW("Invalid parameter: trace is static: "
- "addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
- ret = -1;
- goto end;
- }
+struct bt_stream *bt_trace_borrow_stream_by_index(
+ struct bt_trace *trace, uint64_t index)
+{
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_VALID_INDEX(index, trace->streams->len);
+ return g_ptr_array_index(trace->streams, index);
+}
- if (!bt_clock_class_is_valid(clock_class)) {
- BT_LOGW("Invalid parameter: clock class is invalid: "
- "trace-addr=%p, trace-name=\"%s\", "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- trace, bt_trace_get_name(trace),
- clock_class, bt_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
+struct bt_stream *bt_trace_borrow_stream_by_id(
+ struct bt_trace *trace, uint64_t id)
+{
+ struct bt_stream *stream = NULL;
+ uint64_t i;
- /* Check for duplicate clock classes */
- if (bt_trace_has_clock_class(trace, clock_class)) {
- BT_LOGW("Invalid parameter: clock class already exists in trace: "
- "trace-addr=%p, trace-name=\"%s\", "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- trace, bt_trace_get_name(trace),
- clock_class, bt_clock_class_get_name(clock_class));
- ret = -1;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- bt_get(clock_class);
- g_ptr_array_add(trace->clock_classes, clock_class);
+ for (i = 0; i < trace->streams->len; i++) {
+ struct bt_stream *stream_candidate =
+ g_ptr_array_index(trace->streams, i);
- if (trace->frozen) {
- BT_LOGV_STR("Freezing added clock class because trace is frozen.");
- bt_clock_class_freeze(clock_class);
+ if (stream_candidate->id == id) {
+ stream = stream_candidate;
+ goto end;
+ }
}
- BT_LOGV("Added clock class to trace: "
- "trace-addr=%p, trace-name=\"%s\", "
- "clock-class-addr=%p, clock-class-name=\"%s\"",
- trace, bt_trace_get_name(trace),
- clock_class, bt_clock_class_get_name(clock_class));
-
end:
- return ret;
+ return stream;
}
-int64_t bt_trace_get_clock_class_count(struct bt_trace *trace)
+uint64_t bt_trace_get_stream_class_count(struct bt_trace *trace)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->clock_classes->len;
+ return (uint64_t) trace->stream_classes->len;
}
-struct bt_clock_class *bt_trace_borrow_clock_class_by_index(
+struct bt_stream_class *bt_trace_borrow_stream_class_by_index(
struct bt_trace *trace, uint64_t index)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(index < trace->clock_classes->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u",
- index, trace->clock_classes->len);
- return g_ptr_array_index(trace->clock_classes, index);
+ BT_ASSERT_PRE_VALID_INDEX(index, trace->stream_classes->len);
+ return g_ptr_array_index(trace->stream_classes, index);
}
-static
-bool packet_header_field_type_is_valid(struct bt_trace *trace,
- struct bt_field_type *packet_header_type)
+struct bt_stream_class *bt_trace_borrow_stream_class_by_id(
+ struct bt_trace *trace, uint64_t id)
{
- int ret;
- bool is_valid = true;
- struct bt_field_type *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;
- }
+ struct bt_stream_class *stream_class = NULL;
+ uint64_t i;
- /* No packet header field type: valid at this point */
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- /* Packet header field type, if it exists, must be a structure */
- if (packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
- BT_LOGW("Invalid packet header field type: must be a structure field type if it exists: "
- "ft-addr=%p, ft-id=%s",
- packet_header_type,
- bt_common_field_type_id_string(packet_header_type->id));
- goto invalid;
- }
+ for (i = 0; i < trace->stream_classes->len; i++) {
+ struct bt_stream_class *stream_class_candidate =
+ g_ptr_array_index(trace->stream_classes, i);
- /*
- * 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_field_type_structure_borrow_field_type_by_name(
- packet_header_type, "magic");
- if (field_type) {
- const char *field_name;
-
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet header field type: `magic` field must be an integer field type: "
- "magic-ft-addr=%p, magic-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
+ if (stream_class_candidate->id == id) {
+ stream_class = stream_class_candidate;
+ goto end;
}
+ }
- if (bt_field_type_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;
- }
+end:
+ return stream_class;
+}
- if (bt_field_type_integer_get_size(field_type) != 32) {
- BT_LOGW("Invalid packet header field type: `magic` field must be a 32-bit unsigned integer field type: "
- "magic-ft-addr=%p, magic-ft-size=%u",
- field_type,
- bt_field_type_integer_get_size(field_type));
- goto invalid;
- }
+struct bt_field_type *bt_trace_borrow_packet_header_field_type(
+ struct bt_trace *trace)
+{
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ return trace->packet_header_ft;
+}
- ret = bt_field_type_structure_borrow_field_by_index(
- packet_header_type, &field_name, NULL, 0);
- BT_ASSERT(ret == 0);
+int bt_trace_set_packet_header_field_type(struct bt_trace *trace,
+ struct bt_field_type *field_type)
+{
+ int ret;
+ struct bt_resolve_field_path_context resolve_ctx = {
+ .packet_header = field_type,
+ .packet_context = NULL,
+ .event_header = NULL,
+ .event_common_context = NULL,
+ .event_specific_context = NULL,
+ .event_payload = NULL,
+ };
- 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;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(field_type, "Field type");
+ BT_ASSERT_PRE_TRACE_HOT(trace);
+ BT_ASSERT_PRE(bt_field_type_get_type_id(field_type) ==
+ BT_FIELD_TYPE_ID_STRUCTURE,
+ "Packet header field type is not a structure field type: %!+F",
+ field_type);
+ ret = bt_resolve_field_paths(field_type, &resolve_ctx);
+ if (ret) {
+ goto end;
}
- /*
- * If there's a `uuid` field, it must be an array field type of
- * length 16 with an 8-bit unsigned integer element field type.
- */
- field_type = bt_field_type_structure_borrow_field_type_by_name(
- packet_header_type, "uuid");
- if (field_type) {
- struct bt_field_type *elem_ft;
-
- if (field_type->id != BT_FIELD_TYPE_ID_ARRAY) {
- BT_LOGW("Invalid packet header field type: `uuid` field must be an array field type: "
- "uuid-ft-addr=%p, uuid-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_array_get_length(field_type) != 16) {
- BT_LOGW("Invalid packet header field type: `uuid` array field type's length must be 16: "
- "uuid-ft-addr=%p, uuid-ft-length=%" PRId64,
- field_type,
- bt_field_type_array_get_length(field_type));
- goto invalid;
- }
-
- elem_ft = bt_field_type_array_borrow_element_field_type(field_type);
- BT_ASSERT(elem_ft);
+ bt_field_type_make_part_of_trace(field_type);
+ bt_put(trace->packet_header_ft);
+ trace->packet_header_ft = bt_get(field_type);
+ bt_field_type_freeze(field_type);
+ BT_LIB_LOGV("Set trace's packet header field type: %!+t", trace);
- if (elem_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
- "elem-ft-addr=%p, elem-ft-id=%s",
- elem_ft,
- bt_common_field_type_id_string(elem_ft->id));
- goto invalid;
- }
-
- if (bt_field_type_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_field_type_integer_get_size(elem_ft) != 8) {
- BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an 8-bit unsigned integer field type: "
- "elem-ft-addr=%p, elem-ft-size=%u",
- elem_ft,
- bt_field_type_integer_get_size(elem_ft));
- goto invalid;
- }
- }
-
- /*
- * The `stream_id` field must exist if there's more than one
- * stream classes in the trace.
- */
- field_type = bt_field_type_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_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_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_field_type_structure_borrow_field_type_by_name(
- packet_header_type, "packet_seq_num");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an integer field type: "
- "stream-id-ft-addr=%p, packet-seq-num-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_trace *trace,
- struct bt_stream_class *stream_class,
- struct bt_field_type *packet_context_type,
- bool check_ts_begin_end_mapped)
-{
- bool is_valid = true;
- struct bt_field_type *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_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_common_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_field_type_structure_borrow_field_type_by_name(
- packet_context_type, "packet_size");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet context field type: `packet_size` field must be an integer field type: "
- "packet-size-ft-addr=%p, packet-size-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_field_type_structure_borrow_field_type_by_name(
- packet_context_type, "content_size");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet context field type: `content_size` field must be an integer field type: "
- "content-size-ft-addr=%p, content-size-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_field_type_structure_borrow_field_type_by_name(
- packet_context_type, "events_discarded");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet context field type: `events_discarded` field must be an integer field type: "
- "events-discarded-ft-addr=%p, events-discarded-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_field_type_structure_borrow_field_type_by_name(
- packet_context_type, "timestamp_begin");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an integer field type: "
- "timestamp-begin-ft-addr=%p, timestamp-begin-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_clock_class *clock_class =
- bt_field_type_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_field_type_structure_borrow_field_type_by_name(
- packet_context_type, "timestamp_end");
- if (field_type) {
- if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
- BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an integer field type: "
- "timestamp-end-ft-addr=%p, timestamp-end-ft-id=%s",
- field_type,
- bt_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- if (bt_field_type_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_clock_class *clock_class =
- bt_field_type_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_trace *trace,
- struct bt_stream_class *stream_class,
- struct bt_field_type *event_header_type)
-{
- bool is_valid = true;
- struct bt_field_type *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_stream_class_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_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_common_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_field_type_structure_borrow_field_type_by_name(
- event_header_type, "id");
- if (field_type) {
- struct bt_field_type *int_ft;
-
- if (field_type->id == BT_FIELD_TYPE_ID_INTEGER) {
- int_ft = field_type;
- } else if (field_type->id == BT_FIELD_TYPE_ID_ENUM) {
- int_ft = bt_field_type_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_common_field_type_id_string(field_type->id));
- goto invalid;
- }
-
- BT_ASSERT(int_ft);
- if (bt_field_type_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_trace *trace)
-{
- int ret = 0;
-
- if (trace->packet_header_field_type) {
- struct bt_clock_class *clock_class = NULL;
-
- ret = bt_field_type_validate_single_clock_class(
- trace->packet_header_field_type,
- &clock_class);
- bt_put(clock_class);
- if (ret || clock_class) {
- BT_LOGW("Trace's packet header field type cannot "
- "contain a field type which is mapped to "
- "a clock class: "
- "trace-addr=%p, trace-name=\"%s\", "
- "clock-class-name=\"%s\"",
- trace, bt_trace_get_name(trace),
- clock_class ?
- bt_clock_class_get_name(clock_class) :
- NULL);
- ret = -1;
- }
- }
-
- return ret;
-}
-
-int bt_trace_add_stream_class(struct bt_trace *trace,
- struct bt_stream_class *stream_class)
-{
- int ret;
- int64_t i;
- int64_t stream_id;
- struct bt_validation_output trace_sc_validation_output = { 0 };
- struct bt_validation_output *ec_validation_outputs = NULL;
- const enum bt_validation_flag trace_sc_validation_flags =
- BT_VALIDATION_FLAG_TRACE |
- BT_VALIDATION_FLAG_STREAM;
- const enum bt_validation_flag ec_validation_flags =
- BT_VALIDATION_FLAG_EVENT;
- struct bt_field_type *packet_header_type = NULL;
- struct bt_field_type *packet_context_type = NULL;
- struct bt_field_type *event_header_type = NULL;
- struct bt_field_type *stream_event_ctx_type = NULL;
- int64_t event_class_count;
- struct bt_trace *current_parent_trace = NULL;
- struct bt_clock_class *expected_clock_class = NULL;
-
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- ret = -1;
- goto end;
- }
-
- if (trace->is_static) {
- BT_LOGW_STR("Invalid parameter: trace is static.");
- ret = -1;
- goto end;
- }
-
- 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_trace_get_name(trace),
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
-
- current_parent_trace = bt_stream_class_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_trace_get_name(current_parent_trace));
- ret = -1;
- goto end;
- }
-
- event_class_count =
- bt_stream_class_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_stream_class_add_event_class() calls did
- * not make this validation since the stream class's
- * direct field types (packet context, event header,
- * event context) could change afterwards. This stream
- * class is about to be frozen and those field types
- * won't be changed if this function succeeds.
- *
- * At this point we're also sure that the stream class's
- * clock, if any, has the same class as the stream
- * class's expected clock class, if any. This is why, if
- * bt_stream_class_validate_single_clock_class()
- * succeeds below, the call to
- * bt_stream_class_map_clock_class() at the end of this
- * function is safe because it maps to the same, single
- * clock class.
- */
- ret = bt_stream_class_validate_single_clock_class(
- stream_class, &expected_clock_class);
- 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_stream_class_get_id(stream_class),
- bt_stream_class_get_name(stream_class),
- expected_clock_class,
- expected_clock_class ?
- bt_clock_class_get_name(expected_clock_class) :
- NULL);
- goto 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_trace_borrow_packet_header_field_type(trace);
- packet_context_type =
- bt_stream_class_borrow_packet_context_field_type(stream_class);
- event_header_type =
- bt_stream_class_borrow_event_header_field_type(stream_class);
- stream_event_ctx_type =
- bt_stream_class_borrow_event_context_field_type(stream_class);
-
- BT_LOGD("Validating trace and stream class field types.");
- ret = bt_validate_class_types(trace->environment,
- packet_header_type, packet_context_type, event_header_type,
- stream_event_ctx_type, NULL, NULL, trace->valid,
- stream_class->valid, 1, &trace_sc_validation_output,
- trace_sc_validation_flags, bt_field_type_copy);
-
- 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_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_event_class *event_class =
- bt_stream_class_borrow_event_class_by_index(
- stream_class, i);
- struct bt_field_type *event_context_type = NULL;
- struct bt_field_type *event_payload_type = NULL;
-
- event_context_type =
- bt_event_class_borrow_context_field_type(
- event_class);
- event_payload_type =
- bt_event_class_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_event_class_get_name(event_class),
- bt_event_class_get_id(event_class));
- ret = bt_validate_class_types(trace->environment,
- trace_sc_validation_output.packet_header_type,
- trace_sc_validation_output.packet_context_type,
- 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, bt_field_type_copy);
-
- 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_stream_class_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_stream_class_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_stream_class_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, true)) {
- 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;
- }
-
- bt_object_set_parent(&stream_class->base, &trace->base);
- g_ptr_array_add(trace->stream_classes, stream_class);
-
- /*
- * At this point we know that the function will be successful.
- * Therefore we can replace the trace and stream class field
- * types with what's in their validation output structure and
- * mark them as valid. We can also replace the field types of
- * all the event classes of the stream class and mark them as
- * valid.
- */
- bt_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_validation_replace_types().
- */
- bt_validation_output_put_types(&trace_sc_validation_output);
-
- for (i = 0; i < event_class_count; i++) {
- struct bt_event_class *event_class =
- bt_stream_class_borrow_event_class_by_index(
- stream_class, i);
-
- bt_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_validation_replace_types().
- */
- bt_validation_output_put_types(&ec_validation_outputs[i]);
- }
-
- /*
- * Freeze the trace and the stream class.
- */
- bt_stream_class_freeze(stream_class);
- bt_trace_freeze(trace);
-
- /*
- * It is safe to set the stream class's unique clock class
- * now because the stream class is frozen.
- */
- if (expected_clock_class) {
- BT_MOVE(stream_class->clock_class, expected_clock_class);
- }
-
- /* Notify listeners of the trace's schema modification. */
- bt_stream_class_visit(stream_class,
- bt_trace_object_modification, trace);
- BT_LOGD("Added stream class to trace: "
- "trace-addr=%p, trace-name=\"%s\", "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64,
- trace, bt_trace_get_name(trace),
- stream_class, bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class));
-
-end:
- if (ret) {
- bt_object_set_parent(&stream_class->base, NULL);
-
- if (ec_validation_outputs) {
- for (i = 0; i < event_class_count; i++) {
- bt_validation_output_put_types(
- &ec_validation_outputs[i]);
- }
- }
- }
-
- g_free(ec_validation_outputs);
- bt_validation_output_put_types(&trace_sc_validation_output);
- bt_put(expected_clock_class);
- return ret;
-}
-
-int64_t bt_trace_get_stream_count(struct bt_trace *trace)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return (int64_t) trace->streams->len;
-}
-
-struct bt_stream *bt_trace_borrow_stream_by_index(
- struct bt_trace *trace, uint64_t index)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(index < trace->streams->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u",
- index, trace->streams->len);
- return g_ptr_array_index(trace->streams, index);
-}
-
-int64_t bt_trace_get_stream_class_count(struct bt_trace *trace)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return (int64_t) trace->stream_classes->len;
-}
-
-struct bt_stream_class *bt_trace_borrow_stream_class_by_index(
- struct bt_trace *trace, uint64_t index)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(index < trace->stream_classes->len,
- "Index is out of bounds: index=%" PRIu64 ", "
- "count=%u",
- index, trace->stream_classes->len);
- return g_ptr_array_index(trace->stream_classes, index);
-}
-
-struct bt_stream_class *bt_trace_borrow_stream_class_by_id(
- struct bt_trace *trace, uint64_t id_param)
-{
- int i;
- struct bt_stream_class *stream_class = NULL;
- int64_t id = (int64_t) id_param;
-
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(id >= 0,
- "Invalid stream class ID: %" PRIu64, id_param);
-
- for (i = 0; i < trace->stream_classes->len; i++) {
- struct bt_stream_class *stream_class_candidate;
-
- stream_class_candidate =
- g_ptr_array_index(trace->stream_classes, i);
-
- if (bt_stream_class_get_id(stream_class_candidate) ==
- (int64_t) id) {
- stream_class = stream_class_candidate;
- goto end;
- }
- }
-
-end:
- return stream_class;
-}
-
-struct bt_clock_class *bt_trace_borrow_clock_class_by_name(
- struct bt_trace *trace, const char *name)
-{
- size_t i;
- struct bt_clock_class *clock_class = NULL;
-
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE_NON_NULL(name, "Name");
-
- for (i = 0; i < trace->clock_classes->len; i++) {
- struct bt_clock_class *cur_clk =
- g_ptr_array_index(trace->clock_classes, i);
- const char *cur_clk_name = bt_clock_class_get_name(cur_clk);
-
- if (!cur_clk_name) {
- goto end;
- }
-
- if (!strcmp(cur_clk_name, name)) {
- clock_class = cur_clk;
- goto end;
- }
- }
-
-end:
- return clock_class;
-}
-
-BT_HIDDEN
-bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
- struct bt_clock_class *clock_class)
-{
- struct 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;
-}
-
-enum bt_byte_order bt_trace_get_native_byte_order(
- struct bt_trace *trace)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->native_byte_order;
-}
-
-int bt_trace_set_native_byte_order(struct bt_trace *trace,
- enum bt_byte_order byte_order)
-{
- 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_trace_get_name(trace));
- ret = -1;
- goto end;
- }
-
- if (byte_order != BT_BYTE_ORDER_LITTLE_ENDIAN &&
- byte_order != BT_BYTE_ORDER_BIG_ENDIAN &&
- byte_order != BT_BYTE_ORDER_NETWORK) {
- BT_LOGW("Invalid parameter: invalid byte order: "
- "addr=%p, name=\"%s\", bo=%s",
- trace, bt_trace_get_name(trace),
- bt_common_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_trace_get_name(trace),
- bt_common_byte_order_string(byte_order));
-
-end:
- return ret;
-}
-
-struct bt_field_type *bt_trace_borrow_packet_header_field_type(
- struct bt_trace *trace)
-{
- BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->packet_header_field_type;
-}
-
-int bt_trace_set_packet_header_field_type(struct bt_trace *trace,
- struct bt_field_type *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_trace_get_name(trace));
- ret = -1;
- goto end;
- }
-
- /* packet_header_type must be a structure. */
- if (packet_header_type &&
- packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
- BT_LOGW("Invalid parameter: packet header field type must be a structure field type if it exists: "
- "addr=%p, name=\"%s\", ft-addr=%p, ft-id=%s",
- trace, bt_trace_get_name(trace),
- packet_header_type,
- bt_common_field_type_id_string(packet_header_type->id));
- ret = -1;
- goto end;
- }
-
- bt_put(trace->packet_header_field_type);
- trace->packet_header_field_type = bt_get(packet_header_type);
- BT_LOGV("Set trace's packet header field type: "
- "addr=%p, name=\"%s\", packet-context-ft-addr=%p",
- trace, bt_trace_get_name(trace), packet_header_type);
-end:
- return ret;
-}
-
-static
-int64_t get_stream_class_count(void *element)
-{
- return bt_trace_get_stream_class_count(
- (struct bt_trace *) element);
-}
-
-static
-void *get_stream_class(void *element, int i)
-{
- return bt_trace_get_stream_class_by_index(
- (struct bt_trace *) element, i);
-}
-
-static
-int visit_stream_class(void *object, bt_visitor visitor,void *data)
-{
- return bt_stream_class_visit(object, visitor, data);
-}
-
-int bt_trace_visit(struct bt_trace *trace,
- bt_visitor visitor, void *data)
-{
- int ret;
- struct bt_visitor_object obj = {
- .object = trace,
- .type = BT_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_trace_get_name(trace));
- ret = visitor_helper(&obj, get_stream_class_count,
- get_stream_class, visit_stream_class, visitor, data);
end:
return ret;
}
-static
-int invoke_listener(struct bt_visitor_object *object, void *data)
-{
- struct listener_wrapper *listener_wrapper = data;
-
- listener_wrapper->listener(object, listener_wrapper->data);
- return 0;
-}
-
-// TODO: add logging to this function once we use it internally.
-int bt_trace_add_listener(struct bt_trace *trace,
- bt_listener_cb listener, void *listener_data)
-{
- int ret = 0;
- struct listener_wrapper *listener_wrapper =
- g_new0(struct listener_wrapper, 1);
-
- if (!trace || !listener || !listener_wrapper) {
- ret = -1;
- goto error;
- }
-
- listener_wrapper->listener = listener;
- listener_wrapper->data = listener_data;
-
- /* Visit the current schema. */
- ret = bt_trace_visit(trace, invoke_listener, listener_wrapper);
- if (ret) {
- goto error;
- }
-
- /*
- * Add listener to the array of callbacks which will be invoked on
- * schema changes.
- */
- g_ptr_array_add(trace->listeners, listener_wrapper);
- return ret;
-error:
- g_free(listener_wrapper);
- return ret;
-}
-
-BT_HIDDEN
-int bt_trace_object_modification(struct bt_visitor_object *object,
- void *trace_ptr)
-{
- size_t i;
- struct bt_trace *trace = trace_ptr;
-
- BT_ASSERT(trace);
- BT_ASSERT(object);
-
- if (trace->listeners->len == 0) {
- goto end;
- }
-
- for (i = 0; i < trace->listeners->len; i++) {
- struct listener_wrapper *listener =
- g_ptr_array_index(trace->listeners, i);
-
- listener->listener(object, listener->data);
- }
-end:
- return 0;
-}
-
bt_bool bt_trace_is_static(struct bt_trace *trace)
{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- return trace->is_static;
+ return (bt_bool) trace->is_static;
}
-int bt_trace_set_is_static(struct bt_trace *trace)
+int bt_trace_make_static(struct bt_trace *trace)
{
- int ret = 0;
- size_t i;
-
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- ret = -1;
- 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;
- }
+ uint64_t i;
- trace->is_static = BT_TRUE;
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ trace->is_static = true;
bt_trace_freeze(trace);
- BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
+ BT_LIB_LOGV("Trace is now static: %!+t", trace);
/* Call all the "trace is static" listeners */
for (i = 0; i < trace->is_static_listeners->len; i++) {
}
}
-end:
- return ret;
+ return 0;
}
int bt_trace_add_is_static_listener(struct bt_trace *trace,
bt_trace_is_static_listener listener,
- bt_trace_listener_removed listener_removed, void *data)
+ bt_trace_listener_removed listener_removed, void *data,
+ uint64_t *listener_id)
{
- int i;
+ uint64_t i;
struct bt_trace_is_static_listener_elem new_elem = {
.func = listener,
.removed = listener_removed,
.data = data,
};
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- i = -1;
- goto end;
- }
-
- if (!listener) {
- BT_LOGW_STR("Invalid parameter: listener is NULL.");
- i = -1;
- goto end;
- }
-
- if (trace->is_static) {
- BT_LOGW("Invalid parameter: trace is already static: "
- "addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
- i = -1;
- goto end;
- }
-
- if (trace->in_remove_listener) {
- BT_LOGW("Cannot call this function during the execution of a remove listener: "
- "addr=%p, name=\"%s\"",
- trace, bt_trace_get_name(trace));
- i = -1;
- goto end;
- }
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE_NON_NULL(listener, "Listener");
+ BT_ASSERT_PRE(!trace->is_static,
+ "Trace is already static: %!+t", trace);
+ BT_ASSERT_PRE(trace->in_remove_listener,
+ "Cannot call this function while executing a "
+ "remove listener: %!+t", trace);
/* Find the next available spot */
for (i = 0; i < trace->is_static_listeners->len; i++) {
g_array_insert_val(trace->is_static_listeners, i, new_elem);
}
- BT_LOGV("Added \"trace is static\" listener: "
- "trace-addr=%p, trace-name=\"%s\", func-addr=%p, "
- "data-addr=%p, listener-id=%d",
- trace, bt_trace_get_name(trace), listener, data, i);
+ if (listener_id) {
+ *listener_id = i;
+ }
-end:
- return i;
+ BT_LIB_LOGV("Added \"trace is static\" listener: "
+ "%![trace-]+t, listener-id=%" PRIu64, trace, i);
+ return 0;
+}
+
+BT_ASSERT_PRE_FUNC
+static
+bool has_listener_id(struct bt_trace *trace, uint64_t listener_id)
+{
+ BT_ASSERT(listener_id < trace->is_static_listeners->len);
+ return (&g_array_index(trace->is_static_listeners,
+ struct bt_trace_is_static_listener_elem,
+ listener_id))->func != NULL;
}
int bt_trace_remove_is_static_listener(
- struct bt_trace *trace, int listener_id)
+ struct bt_trace *trace, uint64_t listener_id)
{
- int ret = 0;
struct bt_trace_is_static_listener_elem *elem;
- if (!trace) {
- BT_LOGW_STR("Invalid parameter: trace is NULL.");
- ret = -1;
- goto end;
- }
-
- if (trace->in_remove_listener) {
- BT_LOGW("Cannot call this function during the execution of a remove listener: "
- "addr=%p, name=\"%s\", listener-id=%d",
- trace, bt_trace_get_name(trace),
- listener_id);
- ret = -1;
- goto end;
- }
-
- if (listener_id < 0) {
- BT_LOGW("Invalid listener ID: must be zero or positive: "
- "listener-id=%d", listener_id);
- ret = -1;
- goto end;
- }
-
- if (listener_id >= trace->is_static_listeners->len) {
- BT_LOGW("Invalid parameter: no listener with this listener ID: "
- "addr=%p, name=\"%s\", listener-id=%d",
- trace, bt_trace_get_name(trace),
- listener_id);
- ret = -1;
- goto end;
- }
-
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ BT_ASSERT_PRE(!trace->is_static,
+ "Trace is already static: %!+t", trace);
+ BT_ASSERT_PRE(trace->in_remove_listener,
+ "Cannot call this function while executing a "
+ "remove listener: %!+t", trace);
+ BT_ASSERT_PRE(has_listener_id(trace, listener_id),
+ "Trace has no such \"trace is static\" listener ID: "
+ "%![trace-]+t, %" PRIu64, trace, listener_id);
elem = &g_array_index(trace->is_static_listeners,
struct bt_trace_is_static_listener_elem,
listener_id);
- if (!elem->func) {
- BT_LOGW("Invalid parameter: no listener with this listener ID: "
- "addr=%p, name=\"%s\", listener-id=%d",
- trace, bt_trace_get_name(trace),
- listener_id);
- ret = -1;
- goto end;
- }
+ BT_ASSERT(elem->func);
if (elem->removed) {
/* Call remove listener */
- BT_LOGV("Calling remove listener: "
- "trace-addr=%p, trace-name=\"%s\", "
- "listener-id=%d", trace, bt_trace_get_name(trace),
- listener_id);
- trace->in_remove_listener = BT_TRUE;
+ BT_LIB_LOGV("Calling remove listener: "
+ "%![trace-]+t, listener-id=%" PRIu64,
+ trace, listener_id);
+ trace->in_remove_listener = true;
elem->removed(trace, elem->data);
- trace->in_remove_listener = BT_FALSE;
+ trace->in_remove_listener = false;
}
elem->func = NULL;
elem->removed = NULL;
elem->data = NULL;
- BT_LOGV("Removed \"trace is static\" listener: "
- "trace-addr=%p, trace-name=\"%s\", "
- "listener-id=%d", trace, bt_trace_get_name(trace),
- listener_id);
+ BT_LIB_LOGV("Removed \"trace is static\" listener: "
+ "%![trace-]+t, listener-id=%" PRIu64,
+ trace, listener_id);
+ return 0;
+}
-end:
- return ret;
+BT_HIDDEN
+void _bt_trace_freeze(struct bt_trace *trace)
+{
+ /* The packet header field type is already frozen */
+ BT_ASSERT(trace);
+ BT_LIB_LOGD("Freezing trace: %!+t", trace);
+ trace->frozen = true;
}
-struct bt_packet_header_field *bt_trace_create_packet_header_field(
- struct bt_trace *trace)
+bt_bool bt_trace_assigns_automatic_stream_class_id(struct bt_trace *trace)
{
- struct bt_field_wrapper *field_wrapper;
+ BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+ return (bt_bool) trace->assigns_automatic_stream_class_id;
+}
+int bt_trace_set_assigns_automatic_stream_class_id(
+ struct bt_trace *trace, bt_bool value)
+{
BT_ASSERT_PRE_NON_NULL(trace, "Trace");
- BT_ASSERT_PRE(trace->packet_header_field_type,
- "Trace has no packet header field type: %!+t",
- trace);
- field_wrapper = bt_field_wrapper_create(
- &trace->packet_header_field_pool,
- (void *) trace->packet_header_field_type);
- if (!field_wrapper) {
- BT_LIB_LOGE("Cannot allocate one packet header field from trace: "
- "%![trace-]+t", trace);
- goto error;
- }
+ BT_ASSERT_PRE_TRACE_HOT(trace);
+ trace->assigns_automatic_stream_class_id = (bool) value;
+ BT_LIB_LOGV("Set trace's automatic stream class ID "
+ "assignment property: %!+t", trace);
+ return 0;
+}
- BT_ASSERT(field_wrapper->field);
+BT_HIDDEN
+void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream)
+{
+ guint count = 0;
+
+ bt_object_set_parent(&stream->base, &trace->base);
+ g_ptr_array_add(trace->streams, stream);
bt_trace_freeze(trace);
- goto end;
-error:
- if (field_wrapper) {
- bt_field_wrapper_destroy(field_wrapper);
- field_wrapper = NULL;
+ if (bt_g_hash_table_contains(trace->stream_classes_stream_count,
+ stream->class)) {
+ count = GPOINTER_TO_UINT(g_hash_table_lookup(
+ trace->stream_classes_stream_count, stream->class));
}
-end:
- return (void *) field_wrapper;
+ g_hash_table_insert(trace->stream_classes_stream_count,
+ stream->class, GUINT_TO_POINTER(count + 1));
+}
+
+BT_HIDDEN
+uint64_t bt_trace_get_automatic_stream_id(struct bt_trace *trace,
+ struct bt_stream_class *stream_class)
+{
+ gpointer orig_key;
+ gpointer value;
+ uint64_t id = 0;
+
+ BT_ASSERT(stream_class);
+ BT_ASSERT(trace);
+ if (g_hash_table_lookup_extended(trace->stream_classes_stream_count,
+ stream_class, &orig_key, &value)) {
+ id = (uint64_t) GPOINTER_TO_UINT(value);
+ }
+
+ return id;
}
#include <babeltrace/ctf-ir/clock-class.h>
#include <babeltrace/ref.h>
#include <babeltrace/assert-internal.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_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 IR: 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 "VALIDATION"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/assert-pre-internal.h>
-#include <babeltrace/ctf-ir/validation-internal.h>
-#include <babeltrace/ctf-ir/resolve-internal.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
-#include <babeltrace/ctf-ir/stream-class-internal.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/event-class-internal.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/values.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ref.h>
-
-/*
- * This function resolves and validates the field types of an event
- * class. Only `event_context_type` and `event_payload_type` are
- * resolved and validated; the other field types are used as eventual
- * resolving targets.
- *
- * All parameters are owned by the caller.
- */
-static
-int validate_event_class_types(struct bt_value *environment,
- struct bt_field_type *packet_header_type,
- struct bt_field_type *packet_context_type,
- struct bt_field_type *event_header_type,
- struct bt_field_type *stream_event_ctx_type,
- struct bt_field_type *event_context_type,
- struct bt_field_type *event_payload_type)
-{
- 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_resolve_types(environment, packet_header_type,
- packet_context_type, event_header_type, stream_event_ctx_type,
- event_context_type, event_payload_type,
- BT_RESOLVE_FLAG_EVENT_CONTEXT |
- BT_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_field_type_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_field_type_validate(event_payload_type);
- if (ret) {
- BT_LOGW("Invalid event class's payload field type: "
- "ret=%d", ret);
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-/*
- * This function resolves and validates the field types of a stream
- * class. Only `packet_context_type`, `event_header_type`, and
- * `stream_event_ctx_type` are resolved and validated; the other field
- * type is used as an eventual resolving target.
- *
- * All parameters are owned by the caller.
- */
-static
-int validate_stream_class_types(struct bt_value *environment,
- struct bt_field_type *packet_header_type,
- struct bt_field_type *packet_context_type,
- struct bt_field_type *event_header_type,
- struct bt_field_type *stream_event_ctx_type)
-{
- 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_resolve_types(environment, packet_header_type,
- packet_context_type, event_header_type, stream_event_ctx_type,
- NULL, NULL,
- BT_RESOLVE_FLAG_PACKET_CONTEXT |
- BT_RESOLVE_FLAG_EVENT_HEADER |
- BT_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_field_type_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_field_type_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_field_type_validate(
- stream_event_ctx_type);
- if (ret) {
- BT_LOGW("Invalid stream class's event context field type: "
- "ret=%d", ret);
- goto end;
- }
- }
-
-end:
- return ret;
-}
-
-/*
- * This function resolves and validates the field types of a trace.
- *
- * All parameters are owned by the caller.
- */
-static
-int validate_trace_types(struct bt_value *environment,
- struct bt_field_type *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_resolve_types(environment, packet_header_type,
- NULL, NULL, NULL, NULL, NULL,
- BT_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_field_type_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_field_type *type)
-{
- int ret = 0;
- enum bt_field_type_id type_id = bt_field_type_get_type_id(type);
-
- switch (type_id) {
- case BT_FIELD_TYPE_ID_SEQUENCE:
- case BT_FIELD_TYPE_ID_VARIANT:
- ret = 1;
- goto end;
- case BT_FIELD_TYPE_ID_ARRAY:
- case BT_FIELD_TYPE_ID_STRUCT:
- {
- int i;
- int field_count = bt_field_type_get_field_count(type);
-
- if (field_count < 0) {
- ret = -1;
- goto end;
- }
-
- for (i = 0; i < field_count; ++i) {
- struct bt_field_type *child_type =
- bt_field_type_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_validate_class_types(struct bt_value *environment,
- struct bt_field_type *packet_header_type,
- struct bt_field_type *packet_context_type,
- struct bt_field_type *event_header_type,
- struct bt_field_type *stream_event_ctx_type,
- struct bt_field_type *event_context_type,
- struct bt_field_type *event_payload_type,
- int trace_valid, int stream_class_valid, int event_class_valid,
- struct bt_validation_output *output,
- enum bt_validation_flag validate_flags,
- bt_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_VALIDATION_FLAG_TRACE;
- }
-
- if (stream_class_valid) {
- output->valid_flags |= BT_VALIDATION_FLAG_STREAM;
- }
-
- if (event_class_valid) {
- output->valid_flags |= BT_VALIDATION_FLAG_EVENT;
- }
-
- /* Own the type parameters */
- bt_get(packet_header_type);
- bt_get(packet_context_type);
- bt_get(event_header_type);
- bt_get(stream_event_ctx_type);
- bt_get(event_context_type);
- bt_get(event_payload_type);
-
- /* Validate trace */
- if ((validate_flags & BT_VALIDATION_FLAG_TRACE) && !trace_valid) {
- struct bt_field_type *packet_header_type_copy = NULL;
-
- /* Create field type copies */
- if (packet_header_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- packet_header_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- packet_header_type_copy = packet_header_type;
- bt_get(packet_header_type_copy);
- goto skip_packet_header_type_copy;
- }
-
- BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
- packet_header_type_copy =
- copy_field_type_func(packet_header_type);
- if (!packet_header_type_copy) {
- ret = -1;
- BT_LOGE_STR("Cannot copy packet header field type.");
- goto error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(packet_header_type_copy);
- }
-
-skip_packet_header_type_copy:
- /* Put original reference and move copy */
- BT_MOVE(packet_header_type, packet_header_type_copy);
-
- /* Validate trace field types */
- valid_ret = validate_trace_types(environment,
- packet_header_type);
- if (valid_ret == 0) {
- /* Trace is valid */
- output->valid_flags |= BT_VALIDATION_FLAG_TRACE;
- }
- }
-
- /* Validate stream class */
- if ((validate_flags & BT_VALIDATION_FLAG_STREAM) &&
- !stream_class_valid) {
- struct bt_field_type *packet_context_type_copy = NULL;
- struct bt_field_type *event_header_type_copy = NULL;
- struct bt_field_type *stream_event_ctx_type_copy = NULL;
-
- if (packet_context_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- packet_context_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- packet_context_type_copy = packet_context_type;
- bt_get(packet_context_type_copy);
- goto skip_packet_context_type_copy;
- }
-
- BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
- packet_context_type_copy =
- copy_field_type_func(packet_context_type);
- if (!packet_context_type_copy) {
- BT_LOGE_STR("Cannot copy packet context field type.");
- goto sc_validation_error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(packet_context_type_copy);
- }
-
-skip_packet_context_type_copy:
- if (event_header_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- event_header_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- event_header_type_copy = event_header_type;
- bt_get(event_header_type_copy);
- goto skip_event_header_type_copy;
- }
-
- BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
- event_header_type_copy =
- copy_field_type_func(event_header_type);
- if (!event_header_type_copy) {
- BT_LOGE_STR("Cannot copy event header field type.");
- goto sc_validation_error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(event_header_type_copy);
- }
-
-skip_event_header_type_copy:
- if (stream_event_ctx_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- stream_event_ctx_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- stream_event_ctx_type_copy =
- stream_event_ctx_type;
- bt_get(stream_event_ctx_type_copy);
- goto skip_stream_event_ctx_type_copy;
- }
-
- BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
- stream_event_ctx_type_copy =
- copy_field_type_func(stream_event_ctx_type);
- if (!stream_event_ctx_type_copy) {
- BT_LOGE_STR("Cannot copy stream event context field type.");
- goto sc_validation_error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(stream_event_ctx_type_copy);
- }
-
-skip_stream_event_ctx_type_copy:
- /* Put original references and move copies */
- BT_MOVE(packet_context_type, packet_context_type_copy);
- BT_MOVE(event_header_type, event_header_type_copy);
- BT_MOVE(stream_event_ctx_type, stream_event_ctx_type_copy);
-
- /* Validate stream class field types */
- valid_ret = validate_stream_class_types(environment,
- packet_header_type, packet_context_type,
- event_header_type, stream_event_ctx_type);
- if (valid_ret == 0) {
- /* Stream class is valid */
- output->valid_flags |= BT_VALIDATION_FLAG_STREAM;
- }
-
- goto sc_validation_done;
-
-sc_validation_error:
- BT_PUT(packet_context_type_copy);
- BT_PUT(event_header_type_copy);
- BT_PUT(stream_event_ctx_type_copy);
- ret = -1;
- goto error;
- }
-
-sc_validation_done:
- /* Validate event class */
- if ((validate_flags & BT_VALIDATION_FLAG_EVENT) &&
- !event_class_valid) {
- struct bt_field_type *event_context_type_copy = NULL;
- struct bt_field_type *event_payload_type_copy = NULL;
-
- if (event_context_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- event_context_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- event_context_type_copy = event_context_type;
- bt_get(event_context_type_copy);
- goto skip_event_context_type_copy;
- }
-
- BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
- event_context_type_copy =
- copy_field_type_func(event_context_type);
- if (!event_context_type_copy) {
- BT_LOGE_STR("Cannot copy event context field type.");
- goto ec_validation_error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(event_context_type_copy);
- }
-
-skip_event_context_type_copy:
- if (event_payload_type) {
- contains_seq_var =
- field_type_contains_sequence_or_variant_ft(
- event_payload_type);
- if (contains_seq_var < 0) {
- ret = contains_seq_var;
- goto error;
- } else if (!contains_seq_var) {
- /* No copy is needed */
- event_payload_type_copy = event_payload_type;
- bt_get(event_payload_type_copy);
- goto skip_event_payload_type_copy;
- }
-
- BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
- event_payload_type_copy =
- copy_field_type_func(event_payload_type);
- if (!event_payload_type_copy) {
- BT_LOGE_STR("Cannot copy event payload field type.");
- goto ec_validation_error;
- }
-
- /*
- * Freeze this copy: if it's returned to the
- * caller, it cannot be modified any way since
- * it will be resolved.
- */
- bt_field_type_freeze(event_payload_type_copy);
- }
-
-skip_event_payload_type_copy:
- /* Put original references and move copies */
- BT_MOVE(event_context_type, event_context_type_copy);
- BT_MOVE(event_payload_type, event_payload_type_copy);
-
- /* Validate event class field types */
- valid_ret = validate_event_class_types(environment,
- packet_header_type, packet_context_type,
- event_header_type, stream_event_ctx_type,
- event_context_type, event_payload_type);
- if (valid_ret == 0) {
- /* Event class is valid */
- output->valid_flags |= BT_VALIDATION_FLAG_EVENT;
- }
-
- goto ec_validation_done;
-
-ec_validation_error:
- BT_PUT(event_context_type_copy);
- BT_PUT(event_payload_type_copy);
- ret = -1;
- goto error;
- }
-
-ec_validation_done:
- /*
- * Validation is complete. Move the field types that were used
- * to validate (and that were possibly altered by the validation
- * process) to the output values.
- */
- BT_MOVE(output->packet_header_type, packet_header_type);
- BT_MOVE(output->packet_context_type, packet_context_type);
- BT_MOVE(output->event_header_type, event_header_type);
- BT_MOVE(output->stream_event_ctx_type, stream_event_ctx_type);
- BT_MOVE(output->event_context_type, event_context_type);
- BT_MOVE(output->event_payload_type, event_payload_type);
- return ret;
-
-error:
- BT_PUT(packet_header_type);
- BT_PUT(packet_context_type);
- BT_PUT(event_header_type);
- BT_PUT(stream_event_ctx_type);
- BT_PUT(event_context_type);
- BT_PUT(event_payload_type);
- return ret;
-}
-
-BT_HIDDEN
-void bt_validation_replace_types(struct bt_trace *trace,
- struct bt_stream_class *stream_class,
- struct bt_event_class *event_class,
- struct bt_validation_output *output,
- enum bt_validation_flag replace_flags)
-{
- if ((replace_flags & BT_VALIDATION_FLAG_TRACE) && trace) {
- bt_field_type_freeze(trace->packet_header_field_type);
- BT_MOVE(trace->packet_header_field_type,
- output->packet_header_type);
- }
-
- if ((replace_flags & BT_VALIDATION_FLAG_STREAM) && stream_class) {
- bt_field_type_freeze(stream_class->packet_context_field_type);
- bt_field_type_freeze(stream_class->event_header_field_type);
- bt_field_type_freeze(stream_class->event_context_field_type);
- BT_MOVE(stream_class->packet_context_field_type,
- output->packet_context_type);
- BT_MOVE(stream_class->event_header_field_type,
- output->event_header_type);
- BT_MOVE(stream_class->event_context_field_type,
- output->stream_event_ctx_type);
- }
-
- if ((replace_flags & BT_VALIDATION_FLAG_EVENT) && event_class) {
- bt_field_type_freeze(event_class->context_field_type);
- bt_field_type_freeze(event_class->payload_field_type);
- BT_MOVE(event_class->context_field_type, output->event_context_type);
- BT_MOVE(event_class->payload_field_type, output->event_payload_type);
- }
-}
-
-BT_HIDDEN
-void bt_validation_output_put_types(
- struct bt_validation_output *output)
-{
- BT_PUT(output->packet_header_type);
- BT_PUT(output->packet_context_type);
- BT_PUT(output->event_header_type);
- BT_PUT(output->stream_event_ctx_type);
- BT_PUT(output->event_context_type);
- BT_PUT(output->event_payload_type);
-}
+++ /dev/null
-/*
- * visitor.c
- *
- * Babeltrace CTF IR - Visitor
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <babeltrace/ctf-ir/visitor-internal.h>
-#include <babeltrace/ref.h>
-
-BT_HIDDEN
-int visitor_helper(struct bt_visitor_object *root,
- bt_child_count_accessor child_counter,
- bt_child_accessor child_accessor,
- bt_child_visitor child_visitor,
- bt_visitor visitor,
- void *data)
-{
- int ret, child_count, i;
-
- ret = visitor(root, data);
- if (ret) {
- goto end;
- }
-
- child_count = child_counter(root->object);
- if (child_count < 0) {
- ret = child_count;
- goto end;
- }
-
- for (i = 0; i < child_count; i++) {
- void *child;
-
- child = child_accessor(root->object, i);
- if (!child) {
- ret = -1;
- goto end;
- }
- ret = child_visitor(child, visitor, data);
- BT_PUT(child);
- if (ret) {
- goto end;
- }
- }
-end:
- return ret;
-}
-
-enum bt_visitor_object_type bt_visitor_object_get_type(
- struct bt_visitor_object *object)
-{
- enum bt_visitor_object_type ret = BT_VISITOR_OBJECT_TYPE_UNKNOWN;
-
- if (!object) {
- goto end;
- }
-
- ret = object->type;
-end:
- return ret;
-}
-
-void *bt_visitor_object_get_object(struct bt_visitor_object *object)
-{
- void *ret = NULL;
-
- if (!object) {
- goto end;
- }
-
- ret = object->object;
-end:
- return ret;
-}
unsigned int alignment, unsigned int size, bt_bool is_signed,
enum bt_ctf_byte_order byte_order)
{
- bt_bool rbo = ((int) byte_order != BT_MY_BYTE_ORDER); /* reverse byte order */
+ /* reverse byte order */
+ bt_bool rbo = (byte_order != BT_CTF_MY_BYTE_ORDER);
if (!bt_ctf_stream_pos_align(pos, alignment))
return -EFAULT;
goto end;
}
- ret = visitor_helper(&obj, get_event_class_count,
+ ret = bt_ctf_visitor_helper(&obj, get_event_class_count,
get_event_class,
visit_event_class, visitor, data);
- BT_LOGV("visitor_helper() returned: ret=%d", ret);
+ BT_LOGV("bt_ctf_visitor_helper() returned: ret=%d", ret);
end:
return ret;
BT_LOGV("Visiting trace: addr=%p, name=\"%s\"",
trace, bt_ctf_trace_get_name(trace));
- ret = visitor_helper(&obj, get_stream_class_count,
+ ret = bt_ctf_visitor_helper(&obj, get_stream_class_count,
get_stream_class, visit_stream_class, visitor, data);
end:
return ret;
}
if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
- byte_order = (int) BT_MY_BYTE_ORDER;
+ byte_order = BT_CTF_MY_BYTE_ORDER;
}
ret = bt_ctf_trace_set_native_byte_order(writer->trace,
struct bt_notification_event *notification = NULL;
struct bt_event *event;
struct bt_graph *graph;
- int ret;
BT_ASSERT_PRE_NON_NULL(notif_iter, "Notification iterator");
BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
goto error;
}
- /*
- * Set packet's properties. This can fail so it happens before
- * creating the notification below. We freeze it after we know
- * this function succeeds.
- */
- if (unlikely(!packet->props_are_set)) {
- ret = bt_packet_set_properties(packet);
- if (ret) {
- BT_LIB_LOGE("Cannot update packet's properties: "
- "%![prev-packet-]+a", packet);
- goto error;
- }
- }
-
/*
* Create notification from pool _after_ we have everything
* (in this case, a valid event object) so that we never have an
BT_ASSERT(!notification->event);
notification->event = event;
bt_packet_set_is_frozen(packet, true);
- bt_packet_validate_properties(packet);
+ bt_event_class_freeze(event_class);
BT_LOGD("Created event notification object: "
"event-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
(struct bt_notification_inactivity *) obj;
BT_LOGD("Destroying inactivity notification: addr=%p", notification);
- bt_clock_value_set_finalize(¬ification->cv_set);
+
+ if (notification->default_cv) {
+ bt_clock_value_recycle(notification->default_cv);
+ }
+
g_free(notification);
}
struct bt_notification *bt_notification_inactivity_create(
- struct bt_private_connection_private_notification_iterator *notif_iter)
+ struct bt_private_connection_private_notification_iterator *notif_iter,
+ struct bt_clock_class *default_clock_class)
{
struct bt_notification_inactivity *notification;
struct bt_notification *ret_notif = NULL;
- int ret;
+ BT_ASSERT_PRE_NON_NULL(notif_iter, "Notification iterator");
+ BT_ASSERT_PRE_NON_NULL(default_clock_class, "Default clock class");
BT_LOGD_STR("Creating inactivity notification object.");
notification = g_new0(struct bt_notification_inactivity, 1);
if (!notification) {
BT_NOTIFICATION_TYPE_INACTIVITY,
bt_notification_inactivity_destroy, NULL);
ret_notif = ¬ification->parent;
- ret = bt_clock_value_set_initialize(¬ification->cv_set);
- if (ret) {
+ notification->default_cv = bt_clock_value_create(default_clock_class);
+ if (!notification->default_cv) {
goto error;
}
return ret_notif;
}
-int bt_notification_inactivity_set_clock_value(struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default)
+int bt_notification_inactivity_set_default_clock_value(
+ struct bt_notification *notif, uint64_t value_cycles)
{
struct bt_notification_inactivity *inactivity = (void *) notif;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
- BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
- BT_ASSERT_PRE_HOT(notif, "Notification", ": %!+n", notif);
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_INACTIVITY);
- BT_ASSERT_PRE(is_default,
- "You can only set a default clock value as of this version.");
- return bt_clock_value_set_set_clock_value(&inactivity->cv_set,
- clock_class, raw_value, is_default);
+ BT_ASSERT_PRE_HOT(notif, "Notification", ": %!+n", notif);
+ bt_clock_value_set_value_inline(inactivity->default_cv, value_cycles);
+ BT_LIB_LOGV("Set inactivity notification's default clock value: "
+ "%![notif-]+n, value=%" PRIu64, notif, value_cycles);
+ return 0;
}
struct bt_clock_value *bt_notification_inactivity_borrow_default_clock_value(
struct bt_notification *notif)
{
struct bt_notification_inactivity *inactivity = (void *) notif;
- struct bt_clock_value *clock_value = NULL;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_INACTIVITY);
- clock_value = inactivity->cv_set.default_cv;
- if (!clock_value) {
- BT_LIB_LOGV("No default clock value: %![notif-]+n", notif);
- }
-
- return clock_value;
+ return inactivity->default_cv;
}
struct bt_stream *stream;
struct bt_stream_class *stream_class;
struct bt_graph *graph;
- int ret;
BT_ASSERT_PRE_NON_NULL(notif_iter, "Notification iterator");
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
stream_class,
bt_stream_class_get_name(stream_class),
bt_stream_class_get_id(stream_class));
-
- if (likely(!packet->props_are_set)) {
- ret = bt_packet_set_properties(packet);
- if (ret) {
- BT_LIB_LOGE("Cannot update packet's properties: "
- "%![prev-packet-]+a", packet);
- goto end;
- }
- }
-
graph = bt_private_connection_private_notification_iterator_borrow_graph(
notif_iter);
notification = (void *) bt_notification_create_from_pool(
bt_object_get_no_null_check_no_parent_check(
¬ification->packet->base);
bt_packet_set_is_frozen(packet, true);
- bt_packet_validate_properties(packet);
BT_LOGD("Created packet beginning notification object: "
"packet-addr=%p, stream-addr=%p, stream-name=\"%s\", "
"stream-class-addr=%p, stream-class-name=\"%s\", "
struct bt_stream *stream;
struct bt_stream_class *stream_class;
struct bt_graph *graph;
- int ret;
BT_ASSERT_PRE_NON_NULL(notif_iter, "Notification iterator");
BT_ASSERT_PRE_NON_NULL(packet, "Packet");
stream_class,
bt_stream_class_get_name(stream_class),
bt_stream_class_get_id(stream_class));
-
- if (unlikely(!packet->props_are_set)) {
- ret = bt_packet_set_properties(packet);
- if (ret) {
- BT_LIB_LOGE("Cannot update packet's properties: "
- "%![prev-packet-]+a", packet);
- goto end;
- }
- }
-
graph = bt_private_connection_private_notification_iterator_borrow_graph(
notif_iter);
notification = (void *) bt_notification_create_from_pool(
bt_object_get_no_null_check_no_parent_check(
¬ification->packet->base);
bt_packet_set_is_frozen(packet, true);
- bt_packet_validate_properties(packet);
BT_LOGD("Created packet end notification object: "
"packet-addr=%p, stream-addr=%p, stream-name=\"%s\", "
"stream-class-addr=%p, stream-class-name=\"%s\", "
#include <babeltrace/compiler-internal.h>
#include <babeltrace/ctf-ir/stream-internal.h>
#include <babeltrace/ctf-ir/stream-class.h>
+#include <babeltrace/ctf-ir/stream-class-internal.h>
#include <babeltrace/graph/notification-stream-internal.h>
#include <babeltrace/graph/private-connection-private-notification-iterator.h>
#include <babeltrace/assert-internal.h>
notification);
BT_LOGD_STR("Putting stream.");
BT_PUT(notification->stream);
- bt_clock_value_set_finalize(¬ification->cv_set);
+
+ if (notification->default_cv) {
+ bt_clock_value_recycle(notification->default_cv);
+ }
+
g_free(notification);
}
{
struct bt_notification_stream_end *notification;
struct bt_stream_class *stream_class;
- int ret;
BT_ASSERT_PRE_NON_NULL(stream, "Stream");
stream_class = bt_stream_borrow_class(stream);
BT_NOTIFICATION_TYPE_STREAM_END,
bt_notification_stream_end_destroy, NULL);
notification->stream = bt_get(stream);
- ret = bt_clock_value_set_initialize(¬ification->cv_set);
- if (ret) {
- goto error;
- }
-
BT_LOGD("Created stream end notification object: "
"stream-addr=%p, stream-name=\"%s\", "
"stream-class-addr=%p, stream-class-name=\"%s\", "
return stream_end->stream;
}
-int bt_notification_stream_end_set_clock_value(struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default)
+int bt_notification_stream_end_set_default_clock_value(
+ struct bt_notification *notif, uint64_t value_cycles)
{
- struct bt_notification_stream_end *stream_end = (void *) notif;
+ int ret = 0;
+ struct bt_notification_stream_end *se_notif = (void *) notif;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
- BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
BT_ASSERT_PRE_HOT(notif, "Notification", ": %!+n", notif);
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_STREAM_END);
- BT_ASSERT_PRE(is_default,
- "You can only set a default clock value as of this version.");
- return bt_clock_value_set_set_clock_value(&stream_end->cv_set,
- clock_class, raw_value, is_default);
+ BT_ASSERT_PRE(se_notif->stream->class->default_clock_class,
+ "Notification's stream class has no default clock class: "
+ "%![notif-]+n, %![sc-]+S", notif, se_notif->stream->class);
+
+ if (!se_notif->default_cv) {
+ se_notif->default_cv = bt_clock_value_create(
+ se_notif->stream->class->default_clock_class);
+ if (!se_notif->default_cv) {
+ ret = -1;
+ goto end;
+ }
+ }
+
+ bt_clock_value_set_value_inline(se_notif->default_cv, value_cycles);
+ BT_LIB_LOGV("Set notification's default clock value: %![notif-]+n, "
+ "value=%" PRIu64, value_cycles);
+
+end:
+ return ret;
}
struct bt_clock_value *bt_notification_stream_end_borrow_default_clock_value(
struct bt_notification *notif)
{
struct bt_notification_stream_end *stream_end = (void *) notif;
- struct bt_clock_value *clock_value = NULL;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_STREAM_END);
- clock_value = stream_end->cv_set.default_cv;
- if (!clock_value) {
- BT_LIB_LOGV("No default clock value: %![notif-]+n", notif);
- }
-
- return clock_value;
+ return stream_end->default_cv;
}
static
notification);
BT_LOGD_STR("Putting stream.");
BT_PUT(notification->stream);
- bt_clock_value_set_finalize(¬ification->cv_set);
+
+ if (notification->default_cv) {
+ bt_clock_value_recycle(notification->default_cv);
+ }
+
g_free(notification);
}
struct bt_private_connection_private_notification_iterator *notif_iter,
struct bt_stream *stream)
{
- int ret;
struct bt_notification_stream_begin *notification;
struct bt_stream_class *stream_class;
BT_NOTIFICATION_TYPE_STREAM_BEGIN,
bt_notification_stream_begin_destroy, NULL);
notification->stream = bt_get(stream);
- ret = bt_clock_value_set_initialize(¬ification->cv_set);
- if (ret) {
- goto error;
- }
-
BT_LOGD("Created stream beginning notification object: "
"stream-addr=%p, stream-name=\"%s\", "
"stream-class-addr=%p, stream-class-name=\"%s\", "
return stream_begin->stream;
}
-int bt_notification_stream_begin_set_clock_value(struct bt_notification *notif,
- struct bt_clock_class *clock_class, uint64_t raw_value,
- bt_bool is_default)
+int bt_notification_stream_begin_set_default_clock_value(
+ struct bt_notification *notif, uint64_t value_cycles)
{
- struct bt_notification_stream_begin *stream_begin = (void *) notif;
+ int ret = 0;
+ struct bt_notification_stream_begin *sb_notif = (void *) notif;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
- BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class");
BT_ASSERT_PRE_HOT(notif, "Notification", ": %!+n", notif);
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_STREAM_BEGIN);
- BT_ASSERT_PRE(is_default,
- "You can only set a default clock value as of this version.");
- return bt_clock_value_set_set_clock_value(&stream_begin->cv_set,
- clock_class, raw_value, is_default);
+ BT_ASSERT_PRE(sb_notif->stream->class->default_clock_class,
+ "Notification's stream class has no default clock class: "
+ "%![notif-]+n, %![sc-]+S", notif, sb_notif->stream->class);
+
+ if (!sb_notif->default_cv) {
+ sb_notif->default_cv = bt_clock_value_create(
+ sb_notif->stream->class->default_clock_class);
+ if (!sb_notif->default_cv) {
+ ret = -1;
+ goto end;
+ }
+ }
+
+ bt_clock_value_set_value_inline(sb_notif->default_cv, value_cycles);
+ BT_LIB_LOGV("Set notification's default clock value: %![notif-]+n, "
+ "value=%" PRIu64, value_cycles);
+
+end:
+ return ret;
}
struct bt_clock_value *bt_notification_stream_begin_borrow_default_clock_value(
struct bt_notification *notif)
{
struct bt_notification_stream_begin *stream_begin = (void *) notif;
- struct bt_clock_value *clock_value = NULL;
BT_ASSERT_PRE_NON_NULL(notif, "Notification");
BT_ASSERT_PRE_NOTIF_IS_TYPE(notif, BT_NOTIFICATION_TYPE_STREAM_BEGIN);
- clock_value = stream_begin->cv_set.default_cv;
- if (!clock_value) {
- BT_LIB_LOGV("No default clock value: %![notif-]+n", notif);
- }
-
- return clock_value;
+ return stream_begin->default_cv;
}
} while (0)
#define BUF_APPEND_UUID(_uuid) \
- BUF_APPEND(", %suuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"", \
- prefix, \
- (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])
+ do { \
+ BUF_APPEND(", %suuid=", prefix); \
+ format_uuid(buf_ch, (_uuid)); \
+ } while (0)
#define PRFIELD(_expr) prefix, (_expr)
static inline void format_clock_value(char **buf_ch, bool extended,
const char *prefix, struct bt_clock_value *clock_value);
+static inline void format_field_path(char **buf_ch, bool extended,
+ const char *prefix, struct bt_field_path *field_path);
+
static inline void format_object(char **buf_ch, bool extended,
const char *prefix, struct bt_object *obj)
{
BUF_APPEND(", %sref-count=%llu", prefix, obj->ref_count);
}
-static inline void format_clock_value_set(char **buf_ch, bool extended,
- const char *prefix, struct bt_clock_value_set *cv_set)
+static inline void format_uuid(char **buf_ch, bt_uuid uuid)
{
- char tmp_prefix[64];
-
- if (!cv_set->clock_values) {
- return;
- }
-
- BUF_APPEND(", %ssize=%u", PRFIELD(cv_set->clock_values->len));
-
- if (cv_set->default_cv) {
- SET_TMP_PREFIX("default-cv-");
- format_clock_value(buf_ch, extended, tmp_prefix,
- cv_set->default_cv);
- }
+ BUF_APPEND("\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
+ (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]);
}
static inline void format_object_pool(char **buf_ch, bool extended,
}
}
+static inline void format_integer_field_type(char **buf_ch,
+ bool extended, const char *prefix,
+ struct bt_field_type *field_type)
+{
+ struct bt_field_type_integer *int_ft = (void *) field_type;
+
+ BUF_APPEND(", %srange-size=%" PRIu64 ", %sbase=%s",
+ PRFIELD(int_ft->range),
+ PRFIELD(bt_common_field_type_integer_preferred_display_base_string(int_ft->base)));
+}
+
+static inline void format_array_field_type(char **buf_ch,
+ bool extended, const char *prefix,
+ struct bt_field_type *field_type)
+{
+ struct bt_field_type_array *array_ft = (void *) field_type;
+
+ BUF_APPEND(", %selement-ft-addr=%p, %selement-ft-id=%s",
+ PRFIELD(array_ft->element_ft),
+ PRFIELD(bt_common_field_type_id_string(array_ft->element_ft->id)));
+}
+
static inline void format_field_type(char **buf_ch, bool extended,
const char *prefix, struct bt_field_type *field_type)
{
- BUF_APPEND(", %stype-id=%s, %salignment=%u",
- PRFIELD(bt_common_field_type_id_string(field_type->id)),
- PRFIELD(field_type->alignment));
+ char tmp_prefix[64];
+
+ BUF_APPEND(", %sid=%s",
+ PRFIELD(bt_common_field_type_id_string(field_type->id)));
if (extended) {
BUF_APPEND(", %sis-frozen=%d", PRFIELD(field_type->frozen));
+ BUF_APPEND(", %sis-part-of-trace=%d",
+ PRFIELD(field_type->part_of_trace));
} else {
return;
}
- if (field_type->id == BT_FIELD_TYPE_ID_UNKNOWN) {
- return;
- }
-
switch (field_type->id) {
- case BT_FIELD_TYPE_ID_INTEGER:
+ case BT_FIELD_TYPE_ID_UNSIGNED_INTEGER:
+ case BT_FIELD_TYPE_ID_SIGNED_INTEGER:
{
- struct bt_field_type_integer *integer = (void *) field_type;
-
- BUF_APPEND(", %ssize=%u, %sis-signed=%d, %sbyte-order=%s, "
- "%sbase=%d, %sencoding=%s, "
- "%smapped-clock-class-addr=%p",
- PRFIELD(integer->size), PRFIELD(integer->is_signed),
- PRFIELD(bt_common_byte_order_string(
- integer->user_byte_order)),
- PRFIELD(integer->base),
- PRFIELD(bt_common_string_encoding_string(
- integer->encoding)),
- PRFIELD(integer->mapped_clock_class));
-
- if (integer->mapped_clock_class) {
- BUF_APPEND(", %smapped-clock-class-name=\"%s\"",
- PRFIELD(bt_clock_class_get_name(
- integer->mapped_clock_class)));
- }
+ format_integer_field_type(buf_ch, extended, prefix, field_type);
break;
}
- case BT_FIELD_TYPE_ID_FLOAT:
+ case BT_FIELD_TYPE_ID_REAL:
{
- struct bt_field_type_floating_point *flt = (void *) field_type;
+ struct bt_field_type_real *real_ft = (void *) field_type;
- BUF_APPEND(", %sexp-dig=%u, %smant-dig=%u, %sbyte-order=%s",
- PRFIELD(flt->exp_dig), PRFIELD(flt->mant_dig),
- PRFIELD(bt_common_byte_order_string(
- flt->user_byte_order)));
+ BUF_APPEND(", %sis-single-precision=%d",
+ PRFIELD(real_ft->is_single_precision));
break;
}
- case BT_FIELD_TYPE_ID_ENUM:
+ case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION:
+ case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION:
{
- struct bt_field_type_enumeration *enm = (void *) field_type;
+ struct bt_field_type_enumeration *enum_ft =
+ (void *) field_type;
+ format_integer_field_type(buf_ch, extended, prefix, field_type);
BUF_APPEND(", %smapping-count=%u",
- PRFIELD(enm->entries->len));
+ PRFIELD(enum_ft->mappings->len));
break;
}
- case BT_FIELD_TYPE_ID_STRING:
+ case BT_FIELD_TYPE_ID_STRUCTURE:
{
- struct bt_field_type_string *str = (void *) field_type;
+ struct bt_field_type_structure *struct_ft =
+ (void *) field_type;
+
+ if (struct_ft->common.named_fts) {
+ BUF_APPEND(", %smember-count=%u",
+ PRFIELD(struct_ft->common.named_fts->len));
+ }
- BUF_APPEND(", %sencoding=%s",
- PRFIELD(bt_common_string_encoding_string(
- str->encoding)));
break;
}
- case BT_FIELD_TYPE_ID_STRUCT:
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
{
- struct bt_field_type_structure *structure = (void *) field_type;
+ struct bt_field_type_static_array *array_ft =
+ (void *) field_type;
- BUF_APPEND(", %sfield-count=%u",
- PRFIELD(structure->fields->len));
+ format_array_field_type(buf_ch, extended, prefix, field_type);
+ BUF_APPEND(", %slength=%" PRIu64, PRFIELD(array_ft->length));
break;
}
- case BT_FIELD_TYPE_ID_SEQUENCE:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
{
- struct bt_field_type_sequence *seq = (void *) field_type;
+ struct bt_field_type_dynamic_array *array_ft =
+ (void *) field_type;
+
+ format_array_field_type(buf_ch, extended, prefix, field_type);
+
+ if (array_ft->length_ft) {
+ SET_TMP_PREFIX("length-ft-");
+ format_field_type(buf_ch, extended, tmp_prefix,
+ array_ft->length_ft);
+ }
+
+ if (array_ft->length_field_path) {
+ SET_TMP_PREFIX("length-field-path-");
+ format_field_path(buf_ch, extended, tmp_prefix,
+ array_ft->length_field_path);
+ }
- BUF_APPEND(", %slength-ft-addr=\"%s\", %selem-ft-addr=%p",
- PRFIELD(seq->length_field_name->str),
- PRFIELD(seq->element_ft));
break;
}
case BT_FIELD_TYPE_ID_VARIANT:
{
- struct bt_field_type_variant *variant = (void *) field_type;
+ struct bt_field_type_variant *var_ft = (void *) field_type;
+
+ if (var_ft->common.named_fts) {
+ BUF_APPEND(", %soption-count=%u",
+ PRFIELD(var_ft->common.named_fts->len));
+ }
+
+ if (var_ft->selector_ft) {
+ SET_TMP_PREFIX("selector-ft-");
+ format_field_type(buf_ch, extended, tmp_prefix,
+ var_ft->selector_ft);
+ }
+
+ if (var_ft->selector_field_path) {
+ SET_TMP_PREFIX("selector-field-path-");
+ format_field_path(buf_ch, extended, tmp_prefix,
+ var_ft->selector_field_path);
+ }
- BUF_APPEND(", %stag-name=\"%s\", %sfield-count=%u",
- PRFIELD(variant->tag_name->str),
- PRFIELD(variant->choices->len));
break;
}
default:
BT_ASSERT(field_type);
- if (field_type->base == 8) {
+ if (field_type->base == BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL) {
fmt = ", %svalue=%" PRIo64;
- } else if (field_type->base == 16) {
+ } else if (field_type->base == BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL) {
fmt = ", %svalue=%" PRIx64;
}
- if (field_type->is_signed) {
+ if (field_type->common.id == BT_FIELD_TYPE_ID_SIGNED_INTEGER ||
+ field_type->common.id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION) {
if (!fmt) {
fmt = ", %svalue=%" PRId64;
}
- BUF_APPEND(fmt, PRFIELD(integer->payload.signd));
+ BUF_APPEND(fmt, PRFIELD(integer->value.i));
} else {
if (!fmt) {
fmt = ", %svalue=%" PRIu64;
}
- BUF_APPEND(fmt, PRFIELD(integer->payload.unsignd));
+ BUF_APPEND(fmt, PRFIELD(integer->value.u));
}
}
static inline void format_field(char **buf_ch, bool extended,
const char *prefix, struct bt_field *field)
{
- struct bt_field *common_field = (void *) field;
-
- BUF_APPEND(", %sis-set=%d", PRFIELD(field->payload_set));
+ BUF_APPEND(", %sis-set=%d", PRFIELD(field->is_set));
if (extended) {
BUF_APPEND(", %sis-frozen=%d", PRFIELD(field->frozen));
BUF_APPEND(", %stype-id=%s",
PRFIELD(bt_common_field_type_id_string(field->type->id)));
- if (!extended || field->type->id == BT_FIELD_TYPE_ID_UNKNOWN ||
- !field->payload_set) {
+ if (!extended || !field->is_set) {
return;
}
switch (field->type->id) {
- case BT_FIELD_TYPE_ID_INTEGER:
+ case BT_FIELD_TYPE_ID_UNSIGNED_INTEGER:
+ case BT_FIELD_TYPE_ID_SIGNED_INTEGER:
+ case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION:
+ case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION:
{
format_field_integer_extended(buf_ch, prefix, field);
break;
}
- case BT_FIELD_TYPE_ID_FLOAT:
+ case BT_FIELD_TYPE_ID_REAL:
{
- struct bt_field_floating_point *flt = (void *) field;
+ struct bt_field_real *real_field = (void *) field;
- BUF_APPEND(", %svalue=%f", PRFIELD(flt->payload));
+ BUF_APPEND(", %svalue=%f", PRFIELD(real_field->value));
break;
}
case BT_FIELD_TYPE_ID_STRING:
BT_ASSERT(str->buf->data);
BUF_APPEND(", %spartial-value=\"%.32s\"",
PRFIELD(str->buf->data));
-
}
+
break;
}
- case BT_FIELD_TYPE_ID_SEQUENCE:
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
{
- struct bt_field_sequence *seq = (void *) field;
+ struct bt_field_array *array_field = (void *) field;
- BUF_APPEND(", %slength=%" PRIu64, PRFIELD(seq->length));
+ BUF_APPEND(", %slength=%" PRIu64, PRFIELD(array_field->length));
- if (seq->elements) {
+ if (array_field->fields) {
BUF_APPEND(", %sallocated-length=%u",
- PRFIELD(seq->elements->len));
+ PRFIELD(array_field->fields->len));
}
+
break;
}
case BT_FIELD_TYPE_ID_VARIANT:
{
- struct bt_field_variant *variant = (void *) field;
-
- BUF_APPEND(", %scur-field-addr=%p",
- PRFIELD(variant->current_field));
- break;
- }
- default:
- break;
- }
-
- if (!common_field->type) {
- return;
- }
+ struct bt_field_variant *var_field = (void *) field;
- switch (common_field->type->id) {
- case BT_FIELD_TYPE_ID_ENUM:
- {
- struct bt_field_integer *integer = (void *) field;
- struct bt_field_type_enumeration *enum_ft =
- (void *) common_field->type;
-
- if (enum_ft->container_ft) {
- if (enum_ft->container_ft->is_signed) {
- BUF_APPEND(", %svalue=%" PRId64,
- PRFIELD(integer->payload.signd));
- } else {
- BUF_APPEND(", %svalue=%" PRIu64,
- PRFIELD(integer->payload.unsignd));
- }
- }
+ BUF_APPEND(", %sselected-field-index=%" PRIu64,
+ PRFIELD(var_field->selected_index));
break;
}
default:
PRFIELD(bt_common_scope_string(field_path->root)));
for (i = 0; i < field_path->indexes->len; i++) {
- int index = g_array_index(field_path->indexes, int, i);
+ uint64_t index = bt_field_path_get_index_by_index_inline(
+ field_path, i);
- BUF_APPEND(", %d", index);
+ BUF_APPEND(", %" PRIu64, index);
}
BUF_APPEND("%s", "]");
{
char tmp_prefix[64];
- if (trace->name) {
- BUF_APPEND(", %sname=\"%s\"", PRFIELD(trace->name->str));
+ if (trace->name.value) {
+ BUF_APPEND(", %sname=\"%s\"", PRFIELD(trace->name.value));
}
if (!extended) {
BUF_APPEND(", %sis-frozen=%d", PRFIELD(trace->frozen));
- if (trace->uuid_set) {
- BUF_APPEND_UUID(trace->uuid);
- }
-
- if (trace->clock_classes) {
- BUF_APPEND(", %sclock-class-count=%u",
- PRFIELD(trace->clock_classes->len));
+ if (trace->uuid.value) {
+ BUF_APPEND_UUID(trace->uuid.value);
}
if (trace->stream_classes) {
PRFIELD(trace->streams->len));
}
- BUF_APPEND(", %spacket-header-ft-addr=%p",
- PRFIELD(trace->packet_header_field_type));
- BUF_APPEND(", %sis-static=%d", PRFIELD(trace->is_static));
+ BUF_APPEND(", %spacket-header-ft-addr=%p, %sis-static=%d, "
+ "%sassigns-auto-sc-id=%d",
+ PRFIELD(trace->packet_header_ft),
+ PRFIELD(trace->is_static),
+ PRFIELD(trace->assigns_automatic_stream_class_id));
SET_TMP_PREFIX("phf-pool-");
format_object_pool(buf_ch, extended, prefix,
&trace->packet_header_field_pool);
struct bt_trace *trace;
char tmp_prefix[64];
- if (stream_class->id_set) {
- BUF_APPEND(", %sid=%" PRId64, PRFIELD(stream_class->id));
- }
+ BUF_APPEND(", %sid=%" PRIu64, PRFIELD(stream_class->id));
- if (stream_class->name) {
- BUF_APPEND(", %sname=\"%s\"", PRFIELD(stream_class->name->str));
+ if (stream_class->name.value) {
+ BUF_APPEND(", %sname=\"%s\"",
+ PRFIELD(stream_class->name.value));
}
if (!extended) {
}
BUF_APPEND(", %spacket-context-ft-addr=%p, "
- "%sevent-header-ft-addr=%p, %sevent-context-ft-addr=%p",
- PRFIELD(stream_class->packet_context_field_type),
- PRFIELD(stream_class->event_header_field_type),
- PRFIELD(stream_class->event_context_field_type));
- trace = bt_stream_class_borrow_trace(stream_class);
+ "%sevent-header-ft-addr=%p, %sevent-common-context-ft-addr=%p",
+ PRFIELD(stream_class->packet_context_ft),
+ PRFIELD(stream_class->event_header_ft),
+ PRFIELD(stream_class->event_common_context_ft));
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
if (!trace) {
return;
}
+ BUF_APPEND(", %sassigns-auto-ec-id=%d, %sassigns-auto-stream-id=%d, "
+ "%spackets-have-discarded-ev-counter-snapshot=%d, "
+ "%spackets-have-packet-counter-snapshot=%d, "
+ "%spackets-have-default-begin-cv=%d, "
+ "%spackets-have-default-end-cv=%d",
+ PRFIELD(stream_class->assigns_automatic_event_class_id),
+ PRFIELD(stream_class->assigns_automatic_stream_id),
+ PRFIELD(stream_class->packets_have_discarded_event_counter_snapshot),
+ PRFIELD(stream_class->packets_have_packet_counter_snapshot),
+ PRFIELD(stream_class->packets_have_default_beginning_cv),
+ PRFIELD(stream_class->packets_have_default_end_cv));
BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
SET_TMP_PREFIX("trace-");
format_trace(buf_ch, false, tmp_prefix, trace);
struct bt_trace *trace;
char tmp_prefix[64];
- BUF_APPEND(", %sid=%" PRId64, PRFIELD(event_class->id));
+ BUF_APPEND(", %sid=%" PRIu64, PRFIELD(event_class->id));
- if (event_class->name) {
+ if (event_class->name.value) {
BUF_APPEND(", %sname=\"%s\"",
- PRFIELD(event_class->name->str));
+ PRFIELD(event_class->name.value));
}
if (!extended) {
return;
}
- BUF_APPEND(", %sis-frozen=%d, %slog-level=%s",
- PRFIELD(event_class->frozen),
- PRFIELD(bt_common_event_class_log_level_string(
- event_class->log_level)));
+ BUF_APPEND(", %sis-frozen=%d", PRFIELD(event_class->frozen));
+
+ if (event_class->log_level.base.avail) {
+ BUF_APPEND(", %slog-level=%s",
+ PRFIELD(bt_common_event_class_log_level_string(
+ (int) event_class->log_level.value)));
+ }
- if (event_class->emf_uri) {
+ if (event_class->emf_uri.value) {
BUF_APPEND(", %semf-uri=\"%s\"",
- PRFIELD(event_class->emf_uri->str));
+ PRFIELD(event_class->emf_uri.value));
}
- BUF_APPEND(", %scontext-ft-addr=%p, %spayload-ft-addr=%p",
- PRFIELD(event_class->context_field_type),
- PRFIELD(event_class->payload_field_type));
+ BUF_APPEND(", %sspecific-context-ft-addr=%p, %spayload-ft-addr=%p",
+ PRFIELD(event_class->specific_context_ft),
+ PRFIELD(event_class->payload_ft));
stream_class = bt_event_class_borrow_stream_class(event_class);
if (!stream_class) {
BUF_APPEND(", %sstream-class-addr=%p", PRFIELD(stream_class));
SET_TMP_PREFIX("stream-class-");
format_stream_class(buf_ch, false, tmp_prefix, stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
if (!trace) {
return;
}
struct bt_trace *trace;
char tmp_prefix[64];
- BUF_APPEND(", %sid=%" PRId64, PRFIELD(stream->id));
+ BUF_APPEND(", %sid=%" PRIu64, PRFIELD(stream->id));
- if (stream->name) {
- BUF_APPEND(", %sname=\"%s\"", PRFIELD(stream->name->str));
+ if (stream->name.value) {
+ BUF_APPEND(", %sname=\"%s\"", PRFIELD(stream->name.value));
}
if (!extended) {
BUF_APPEND(", %sstream-class-addr=%p", PRFIELD(stream_class));
SET_TMP_PREFIX("stream-class-");
format_stream_class(buf_ch, false, tmp_prefix, stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
if (!trace) {
return;
}
BUF_APPEND(", %sis-frozen=%d, %sheader-field-addr=%p, "
"%scontext-field-addr=%p",
PRFIELD(packet->frozen),
- PRFIELD(packet->header ? packet->header->field : NULL),
- PRFIELD(packet->context));
+ PRFIELD(packet->header_field ? packet->header_field->field : NULL),
+ PRFIELD(packet->context_field ? packet->context_field->field : NULL));
stream = bt_packet_borrow_stream(packet);
if (!stream) {
return;
}
+ if (packet->default_beginning_cv) {
+ SET_TMP_PREFIX("default-begin-cv-");
+ format_clock_value(buf_ch, true, tmp_prefix,
+ packet->default_beginning_cv);
+ }
+
+ if (packet->default_end_cv) {
+ SET_TMP_PREFIX("default-end-cv-");
+ format_clock_value(buf_ch, true, tmp_prefix,
+ packet->default_end_cv);
+ }
+
+ if (packet->discarded_event_counter_snapshot.base.avail) {
+ BUF_APPEND(", %sdiscarded-ev-counter-snapshot=%" PRIu64,
+ PRFIELD(packet->discarded_event_counter_snapshot.value));
+ }
+
+ if (packet->packet_counter_snapshot.base.avail) {
+ BUF_APPEND(", %spacket-counter-snapshot=%" PRIu64,
+ PRFIELD(packet->packet_counter_snapshot.value));
+ }
+
BUF_APPEND(", %sstream-addr=%p", PRFIELD(stream));
SET_TMP_PREFIX("stream-");
format_stream(buf_ch, false, tmp_prefix, stream);
- trace = (struct bt_trace *)
- bt_object_borrow_parent(&stream->base);
+ trace = (struct bt_trace *) bt_object_borrow_parent(&stream->base);
if (!trace) {
return;
}
}
BUF_APPEND(", %sis-frozen=%d, %sheader-field-addr=%p, "
- "%sstream-context-field-addr=%p, "
- "%scontext-field-addr=%p, %spayload-field-addr=%p, ",
+ "%scommon-context-field-addr=%p, "
+ "%specific-scontext-field-addr=%p, "
+ "%spayload-field-addr=%p, ",
PRFIELD(event->frozen),
PRFIELD(event->header_field ?
event->header_field->field : NULL),
- PRFIELD(event->stream_event_context_field),
- PRFIELD(event->context_field),
+ PRFIELD(event->common_context_field),
+ PRFIELD(event->specific_context_field),
PRFIELD(event->payload_field));
BUF_APPEND(", %sevent-class-addr=%p", PRFIELD(event->class));
format_stream_class(buf_ch, false, tmp_prefix,
stream_class);
- trace = bt_stream_class_borrow_trace(stream_class);
+ trace = bt_stream_class_borrow_trace_inline(stream_class);
if (trace) {
BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
SET_TMP_PREFIX("trace-");
}
}
- SET_TMP_PREFIX("cvs-");
- format_clock_value_set(buf_ch, extended, tmp_prefix, &event->cv_set);
+ if (event->default_cv) {
+ SET_TMP_PREFIX("default-cv-");
+ format_clock_value(buf_ch, true, tmp_prefix,
+ event->default_cv);
+ }
+
packet = bt_event_borrow_packet(event);
if (!packet) {
return;
{
char tmp_prefix[64];
- BUF_APPEND(", %sname=\"%s\", %sfreq=%" PRIu64,
- PRFIELD(clock_class->name->str),
- PRFIELD(clock_class->frequency));
+ if (clock_class->name.value) {
+ BUF_APPEND(", %sname=\"%s\"", PRFIELD(clock_class->name.value));
+ }
+
+ BUF_APPEND(", %sfreq=%" PRIu64, PRFIELD(clock_class->frequency));
if (!extended) {
return;
}
- if (clock_class->description) {
- BUF_APPEND(", %spartial-description=\"%.32s\"",
- PRFIELD(clock_class->description->str));
+ if (clock_class->description.value) {
+ BUF_APPEND(", %spartial-descr=\"%.32s\"",
+ PRFIELD(clock_class->description.value));
+ }
+
+ if (clock_class->uuid.value) {
+ BUF_APPEND_UUID(clock_class->uuid.value);
}
BUF_APPEND(", %sis-frozen=%d, %sprecision=%" PRIu64 ", "
"%soffset-s=%" PRId64 ", "
- "%soffset-cycles=%" PRId64 ", %sis-absolute=%d",
+ "%soffset-cycles=%" PRIu64 ", %sis-absolute=%d, "
+ "%sbase-offset-ns=%" PRId64,
PRFIELD(clock_class->frozen), PRFIELD(clock_class->precision),
- PRFIELD(clock_class->offset_s), PRFIELD(clock_class->offset),
- PRFIELD(clock_class->absolute));
-
- if (clock_class->uuid_set) {
- BUF_APPEND_UUID(clock_class->uuid);
- }
+ PRFIELD(clock_class->offset_seconds),
+ PRFIELD(clock_class->offset_cycles),
+ PRFIELD(clock_class->is_absolute),
+ PRFIELD(clock_class->base_offset.value_ns));
SET_TMP_PREFIX("cv-pool-");
format_object_pool(buf_ch, extended, prefix, &clock_class->cv_pool);
const char *prefix, struct bt_clock_value *clock_value)
{
char tmp_prefix[64];
- BUF_APPEND(", %sraw-value=%" PRIu64 ", %sns-from-epoch=%" PRId64,
- PRFIELD(clock_value->value),
- PRFIELD(clock_value->ns_from_epoch));
+ BUF_APPEND(", %svalue=%" PRIu64 ", %sns-from-origin=%" PRId64,
+ PRFIELD(clock_value->value_cycles),
+ PRFIELD(clock_value->ns_from_origin));
if (!extended) {
return;
}
- BUF_APPEND(", %sis-frozen=%d, %sis-set=%d",
- PRFIELD(clock_value->frozen), PRFIELD(clock_value->is_set));
+ BUF_APPEND(", %sis-set=%d", PRFIELD(clock_value->is_set));
BUF_APPEND(", %sclock-class-addr=%p",
PRFIELD(clock_value->clock_class));
SET_TMP_PREFIX("clock-class-");
/* skip "%!" */
fmt_ch += 2;
+ if (*fmt_ch == 'u') {
+ /* UUID */
+ obj = va_arg(*args, void *);
+ format_uuid(buf_ch, obj);
+ goto update_fmt;
+ }
+
if (*fmt_ch == '[') {
/* local prefix */
fmt_ch++;
case 'x':
format_connection(buf_ch, extended, prefix, obj);
break;
- case 'u':
+ case 'l':
format_plugin(buf_ch, extended, prefix, obj);
break;
case 'g':
-SUBDIRS = utils ctf text
+SUBDIRS = utils text ctf
# libctfcopytrace
if ENABLE_DEBUG_INFO
-SUBDIRS = utils btr notif-iter metadata
+SUBDIRS = metadata btr notif-iter utils
noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-common.la
libbabeltrace_plugin_ctf_common_la_SOURCES = print.h
libbabeltrace_plugin_ctf_common_la_LIBADD = \
- $(builddir)/btr/libctf-btr.la \
$(builddir)/metadata/libctf-parser.la \
$(builddir)/metadata/libctf-ast.la \
+ $(builddir)/btr/libctf-btr.la \
$(builddir)/notif-iter/libctf-notif-iter.la \
$(builddir)/utils/libctf-utils.la
#include <glib.h>
#include "btr.h"
+#include "../metadata/ctf-meta.h"
#define DIV8(_x) ((_x) >> 3)
#define BYTES_TO_BITS(_x) ((_x) * 8)
* * Sequence
* * Variant
*/
- struct bt_field_type *base_type;
+ struct ctf_field_type *base_type;
/* Length of base field (always 1 for variant types) */
int64_t base_len;
- /* Lndex of next field to read */
+ /* Index of next field to read */
int64_t index;
};
struct stack *stack;
/* Current basic field type */
- struct bt_field_type *cur_basic_field_type;
+ struct ctf_field_type *cur_basic_field_type;
/* Current state */
enum btr_state state;
* types for which the common boundary is not the boundary of
* a byte cannot have different byte orders.
*
- * This is set to BT_BYTE_ORDER_UNKNOWN on reset and when
- * the last basic field type was a string type.
+ * This is set to -1 on reset and when the last basic field type
+ * was a string type.
*/
- enum bt_byte_order last_bo;
+ enum ctf_byte_order last_bo;
/* Current byte order (copied to last_bo after a successful read) */
- enum bt_byte_order cur_bo;
+ enum ctf_byte_order cur_bo;
/* Stitch buffer infos */
struct {
g_free(stack);
}
-static inline
-int64_t get_compound_field_type_length(struct bt_btr *btr,
- struct bt_field_type *field_type)
-{
- int64_t length;
-
- switch (bt_field_type_get_type_id(field_type)) {
- case BT_FIELD_TYPE_ID_STRUCT:
- length = (int64_t) bt_field_type_structure_get_field_count(
- field_type);
- break;
- case BT_FIELD_TYPE_ID_VARIANT:
- /* Variant field types always "contain" a single type */
- length = 1;
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- length = bt_field_type_array_get_length(field_type);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- length = btr->user.cbs.query.get_sequence_length(field_type,
- btr->user.data);
- break;
- default:
- BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
- "ft-addr=%p, ft-id=%s",
- btr, field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(field_type)));
- length = BT_BTR_STATUS_ERROR;
- }
-
- return length;
-}
-
static
-int stack_push(struct stack *stack, struct bt_field_type *base_type,
+int stack_push(struct stack *stack, struct ctf_field_type *base_type,
size_t base_len)
{
struct stack_entry *entry;
BT_ASSERT(stack);
BT_ASSERT(base_type);
BT_LOGV("Pushing field type on stack: stack-addr=%p, "
- "ft-addr=%p, ft-id=%s, base-length=%zu, "
+ "ft-addr=%p, ft-id=%d, base-length=%zu, "
"stack-size-before=%zu, stack-size-after=%zu",
- stack, base_type, bt_common_field_type_id_string(
- bt_field_type_get_type_id(base_type)),
+ stack, base_type, base_type->id,
base_len, stack->size, stack->size + 1);
if (stack->entries->len == stack->size) {
return 0;
}
+static inline
+int64_t get_compound_field_type_length(struct bt_btr *btr,
+ struct ctf_field_type *ft)
+{
+ int64_t length;
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ length = (int64_t) struct_ft->members->len;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ /* Variant field types always "contain" a single type */
+ length = 1;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ {
+ struct ctf_field_type_array *array_ft = (void *) ft;
+
+ length = (int64_t) array_ft->length;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ length = btr->user.cbs.query.get_sequence_length(ft,
+ btr->user.data);
+ break;
+ default:
+ abort();
+ }
+
+ return length;
+}
+
static
-int stack_push_with_len(struct bt_btr *btr,
- struct bt_field_type *base_type)
+int stack_push_with_len(struct bt_btr *btr, struct ctf_field_type *base_type)
{
- int ret = 0;
- int64_t base_len = get_compound_field_type_length(btr, base_type);
+ int ret;
+ int64_t length = get_compound_field_type_length(btr, base_type);
- if (base_len < 0) {
+ if (length < 0) {
BT_LOGW("Cannot get compound field type's field count: "
- "btr-addr=%p, ft-addr=%p, ft-id=%s",
- btr, base_type, bt_common_field_type_id_string(
- bt_field_type_get_type_id(base_type)));
+ "btr-addr=%p, ft-addr=%p, ft-id=%d",
+ btr, base_type, base_type->id);
ret = BT_BTR_STATUS_ERROR;
goto end;
}
- ret = stack_push(btr->stack, base_type, (size_t) base_len);
+ ret = stack_push(btr->stack, base_type, (size_t) length);
end:
return ret;
return btr->buf.offset + btr->buf.at;
}
-static inline
-int get_basic_field_type_size(struct bt_btr *btr,
- struct bt_field_type *field_type)
-{
- int size;
-
- switch (bt_field_type_get_type_id(field_type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
- size = bt_field_type_integer_get_size(field_type);
- break;
- case BT_FIELD_TYPE_ID_FLOAT:
- {
- int exp_dig, mant_dig;
-
- exp_dig =
- bt_field_type_floating_point_get_exponent_digits(
- field_type);
- mant_dig =
- bt_field_type_floating_point_get_mantissa_digits(
- field_type);
- BT_ASSERT(exp_dig >= 0);
- BT_ASSERT(mant_dig >= 0);
- size = exp_dig + mant_dig;
- break;
- }
- case BT_FIELD_TYPE_ID_ENUM:
- {
- struct bt_field_type *int_type;
-
- int_type =
- bt_field_type_enumeration_borrow_container_field_type(
- field_type);
- BT_ASSERT(int_type);
- size = get_basic_field_type_size(btr, int_type);
- break;
- }
- default:
- size = BT_BTR_STATUS_ERROR;
- break;
- }
-
- return size;
-}
-
static
void stitch_reset(struct bt_btr *btr)
{
}
static inline
-enum bt_btr_status read_unsigned_bitfield(const uint8_t *buf, size_t at,
- int64_t field_size, enum bt_byte_order bo, uint64_t *v)
+void read_unsigned_bitfield(const uint8_t *buf, size_t at,
+ unsigned int field_size, enum ctf_byte_order bo,
+ uint64_t *v)
{
- enum bt_btr_status status = BT_BTR_STATUS_OK;
-
switch (bo) {
- case BT_BYTE_ORDER_BIG_ENDIAN:
- case BT_BYTE_ORDER_NETWORK:
+ case CTF_BYTE_ORDER_BIG:
bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
break;
- case BT_BYTE_ORDER_LITTLE_ENDIAN:
+ case CTF_BYTE_ORDER_LITTLE:
bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
break;
default:
- BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo);
abort();
}
- BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64 ", "
- "bo=%s, val=%" PRIu64, at, field_size,
- bt_common_byte_order_string(bo), *v);
- return status;
+ BT_LOGV("Read unsigned bit array: cur=%zu, size=%u, "
+ "bo=%d, val=%" PRIu64, at, field_size, bo, *v);
}
static inline
-enum bt_btr_status read_signed_bitfield(const uint8_t *buf, size_t at,
- int64_t field_size, enum bt_byte_order bo, int64_t *v)
+void read_signed_bitfield(const uint8_t *buf, size_t at,
+ unsigned int field_size, enum ctf_byte_order bo, int64_t *v)
{
- enum bt_btr_status status = BT_BTR_STATUS_OK;
-
switch (bo) {
- case BT_BYTE_ORDER_BIG_ENDIAN:
- case BT_BYTE_ORDER_NETWORK:
+ case CTF_BYTE_ORDER_BIG:
bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
break;
- case BT_BYTE_ORDER_LITTLE_ENDIAN:
+ case CTF_BYTE_ORDER_LITTLE:
bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
break;
default:
- BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo);
abort();
}
- BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64 ", "
- "bo=%s, val=%" PRId64, at, field_size,
- bt_common_byte_order_string(bo), *v);
- return status;
+ BT_LOGV("Read signed bit array: cur=%zu, size=%u, "
+ "bo=%d, val=%" PRId64, at, field_size, bo, *v);
}
typedef enum bt_btr_status (* read_basic_and_call_cb_t)(struct bt_btr *,
static inline
enum bt_btr_status validate_contiguous_bo(struct bt_btr *btr,
- enum bt_byte_order next_bo)
+ enum ctf_byte_order next_bo)
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
}
/* Always valid if last byte order is unknown */
- if (btr->last_bo == BT_BYTE_ORDER_UNKNOWN) {
+ if (btr->last_bo == -1) {
goto end;
}
/* Always valid if next byte order is unknown */
- if (next_bo == BT_BYTE_ORDER_UNKNOWN) {
+ if (next_bo == -1) {
goto end;
}
/* Make sure last byte order is compatible with the next byte order */
switch (btr->last_bo) {
- case BT_BYTE_ORDER_BIG_ENDIAN:
- case BT_BYTE_ORDER_NETWORK:
- if (next_bo != BT_BYTE_ORDER_BIG_ENDIAN &&
- next_bo != BT_BYTE_ORDER_NETWORK) {
+ case CTF_BYTE_ORDER_BIG:
+ if (next_bo != CTF_BYTE_ORDER_BIG) {
status = BT_BTR_STATUS_ERROR;
}
break;
- case BT_BYTE_ORDER_LITTLE_ENDIAN:
- if (next_bo != BT_BYTE_ORDER_LITTLE_ENDIAN) {
+ case CTF_BYTE_ORDER_LITTLE:
+ if (next_bo != CTF_BYTE_ORDER_LITTLE) {
status = BT_BTR_STATUS_ERROR;
}
break;
end:
if (status < 0) {
BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
- "btr-addr=%p, last-bo=%s, next-bo=%s",
- btr, bt_common_byte_order_string(btr->last_bo),
- bt_common_byte_order_string(next_bo));
+ "btr-addr=%p, last-bo=%d, next-bo=%d",
+ btr, btr->last_bo, next_bo);
}
return status;
enum bt_btr_status read_basic_float_and_call_cb(struct bt_btr *btr,
const uint8_t *buf, size_t at)
{
- int ret;
double dblval;
- int64_t field_size;
- enum bt_byte_order bo;
+ unsigned int field_size;
+ enum ctf_byte_order bo;
enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct ctf_field_type_float *ft = (void *) btr->cur_basic_field_type;
- field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
- bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
+ BT_ASSERT(ft);
+ field_size = ft->base.size;
+ bo = ft->base.byte_order;
btr->cur_bo = bo;
switch (field_size) {
float f;
} f32;
- ret = bt_field_type_floating_point_get_mantissa_digits(
- btr->cur_basic_field_type);
- BT_ASSERT(ret == 24);
- ret = bt_field_type_floating_point_get_exponent_digits(
- btr->cur_basic_field_type);
- BT_ASSERT(ret == 8);
- status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
- if (status != BT_BTR_STATUS_OK) {
- BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
- "btr-addr=%p, status=%s",
- btr, bt_btr_status_string(status));
- goto end;
- }
-
+ read_unsigned_bitfield(buf, at, field_size, bo, &v);
f32.u = (uint32_t) v;
dblval = (double) f32.f;
break;
double d;
} f64;
- ret = bt_field_type_floating_point_get_mantissa_digits(
- btr->cur_basic_field_type);
- BT_ASSERT(ret == 53);
- ret = bt_field_type_floating_point_get_exponent_digits(
- btr->cur_basic_field_type);
- BT_ASSERT(ret == 11);
- status = read_unsigned_bitfield(buf, at, field_size, bo,
- &f64.u);
- if (status != BT_BTR_STATUS_OK) {
- BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
- "btr-addr=%p, status=%s",
- btr, bt_btr_status_string(status));
- goto end;
- }
-
+ read_unsigned_bitfield(buf, at, field_size, bo, &f64.u);
dblval = f64.d;
break;
}
default:
/* Only 32-bit and 64-bit fields are supported currently */
- BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
- "btr-addr=%p", btr);
- status = BT_BTR_STATUS_ERROR;
- goto end;
+ abort();
}
BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
}
}
-end:
return status;
}
static inline
-enum bt_btr_status read_basic_int_and_call(struct bt_btr *btr,
- const uint8_t *buf, size_t at,
- struct bt_field_type *int_type,
- struct bt_field_type *orig_type)
+enum bt_btr_status read_basic_int_and_call_cb(struct bt_btr *btr,
+ const uint8_t *buf, size_t at)
{
- bt_bool signd;
- int64_t field_size;
- enum bt_byte_order bo;
+ unsigned int field_size;
+ enum ctf_byte_order bo;
enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct ctf_field_type_int *ft = (void *) btr->cur_basic_field_type;
- signd = bt_field_type_integer_is_signed(int_type);
- field_size = get_basic_field_type_size(btr, int_type);
- if (field_size < 1) {
- BT_LOGW("Cannot get integer field type's size: "
- "btr=%p, at=%zu, ft-addr=%p",
- btr, at, int_type);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
- bo = bt_field_type_get_byte_order(int_type);
+ field_size = ft->base.size;
+ bo = ft->base.byte_order;
/*
* Update current byte order now because we could be reading
*/
btr->cur_bo = bo;
- if (signd) {
+ if (ft->is_signed) {
int64_t v;
- status = read_signed_bitfield(buf, at, field_size, bo, &v);
- if (status != BT_BTR_STATUS_OK) {
- BT_LOGW("Cannot read signed bit array for signed integer field: "
- "btr-addr=%p, status=%s",
- btr, bt_btr_status_string(status));
- goto end;
- }
+ read_signed_bitfield(buf, at, field_size, bo, &v);
if (btr->user.cbs.types.signed_int) {
BT_LOGV("Calling user function (signed integer).");
} else {
uint64_t v;
- status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
- if (status != BT_BTR_STATUS_OK) {
- BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
- "btr-addr=%p, status=%s",
- btr, bt_btr_status_string(status));
- goto end;
- }
+ read_unsigned_bitfield(buf, at, field_size, bo, &v);
if (btr->user.cbs.types.unsigned_int) {
BT_LOGV("Calling user function (unsigned integer).");
}
}
-end:
- return status;
-}
-
-static
-enum bt_btr_status read_basic_int_and_call_cb(struct bt_btr *btr,
- const uint8_t *buf, size_t at)
-{
- return read_basic_int_and_call(btr, buf, at, btr->cur_basic_field_type,
- btr->cur_basic_field_type);
-}
-
-static
-enum bt_btr_status read_basic_enum_and_call_cb(struct bt_btr *btr,
- const uint8_t *buf, size_t at)
-{
- struct bt_field_type *int_field_type;
- enum bt_btr_status status = BT_BTR_STATUS_OK;
-
- int_field_type = bt_field_type_enumeration_borrow_container_field_type(
- btr->cur_basic_field_type);
- BT_ASSERT(int_field_type);
- status = read_basic_int_and_call(btr, buf, at,
- int_field_type, btr->cur_basic_field_type);
return status;
}
static inline
-enum bt_btr_status read_basic_type_and_call_continue(struct bt_btr *btr,
+enum bt_btr_status read_bit_array_type_and_call_continue(struct bt_btr *btr,
read_basic_and_call_cb_t read_basic_and_call_cb)
{
size_t available;
- int64_t field_size;
- int64_t needed_bits;
+ size_t needed_bits;
enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct ctf_field_type_bit_array *ft =
+ (void *) btr->cur_basic_field_type;
if (!at_least_one_bit_left(btr)) {
BT_LOGV("Reached end of data: btr-addr=%p", btr);
goto end;
}
- field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
- if (field_size < 1) {
- BT_LOGW("Cannot get basic field type's size: "
- "btr-addr=%p, ft-addr=%p",
- btr, btr->cur_basic_field_type);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
available = available_bits(btr);
- needed_bits = field_size - btr->stitch.at;
+ needed_bits = ft->size - btr->stitch.at;
BT_LOGV("Continuing basic field decoding: "
- "btr-addr=%p, field-size=%" PRId64 ", needed-size=%" PRId64 ", "
+ "btr-addr=%p, field-size=%u, needed-size=%" PRId64 ", "
"available-size=%zu",
- btr, field_size, needed_bits, available);
+ btr, ft->size, needed_bits, available);
if (needed_bits <= available) {
/* We have all the bits; append to stitch, then decode */
stitch_append_from_buf(btr, needed_bits);
}
static inline
-enum bt_btr_status read_basic_type_and_call_begin(struct bt_btr *btr,
+enum bt_btr_status read_bit_array_type_and_call_begin(struct bt_btr *btr,
read_basic_and_call_cb_t read_basic_and_call_cb)
{
size_t available;
- int64_t field_size;
- enum bt_byte_order bo;
enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct ctf_field_type_bit_array *ft =
+ (void *) btr->cur_basic_field_type;
if (!at_least_one_bit_left(btr)) {
BT_LOGV("Reached end of data: btr-addr=%p", btr);
goto end;
}
- field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
- if (field_size < 1) {
- BT_LOGW("Cannot get basic field type's size: "
- "btr-addr=%p, ft-addr=%p",
- btr, btr->cur_basic_field_type);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
- bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
- status = validate_contiguous_bo(btr, bo);
+ status = validate_contiguous_bo(btr, ft->byte_order);
if (status != BT_BTR_STATUS_OK) {
/* validate_contiguous_bo() logs errors */
goto end;
available = available_bits(btr);
- if (field_size <= available) {
+ if (ft->size <= available) {
/* We have all the bits; decode and set now */
BT_ASSERT(btr->buf.addr);
status = read_basic_and_call_cb(btr, btr->buf.addr,
goto end;
}
- consume_bits(btr, field_size);
+ consume_bits(btr, ft->size);
if (stack_empty(btr->stack)) {
/* Root is a basic type */
enum bt_btr_status read_basic_int_type_and_call_begin(
struct bt_btr *btr)
{
- return read_basic_type_and_call_begin(btr, read_basic_int_and_call_cb);
+ return read_bit_array_type_and_call_begin(btr, read_basic_int_and_call_cb);
}
static inline
enum bt_btr_status read_basic_int_type_and_call_continue(
struct bt_btr *btr)
{
- return read_basic_type_and_call_continue(btr,
+ return read_bit_array_type_and_call_continue(btr,
read_basic_int_and_call_cb);
}
enum bt_btr_status read_basic_float_type_and_call_begin(
struct bt_btr *btr)
{
- return read_basic_type_and_call_begin(btr,
+ return read_bit_array_type_and_call_begin(btr,
read_basic_float_and_call_cb);
}
enum bt_btr_status read_basic_float_type_and_call_continue(
struct bt_btr *btr)
{
- return read_basic_type_and_call_continue(btr,
+ return read_bit_array_type_and_call_continue(btr,
read_basic_float_and_call_cb);
}
-static inline
-enum bt_btr_status read_basic_enum_type_and_call_begin(
- struct bt_btr *btr)
-{
- return read_basic_type_and_call_begin(btr,
- read_basic_enum_and_call_cb);
-}
-
-static inline
-enum bt_btr_status read_basic_enum_type_and_call_continue(
- struct bt_btr *btr)
-{
- return read_basic_type_and_call_continue(btr,
- read_basic_enum_and_call_cb);
-}
-
static inline
enum bt_btr_status read_basic_string_type_and_call(
struct bt_btr *btr, bool begin)
BT_ASSERT(btr->cur_basic_field_type);
- switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
+ switch (btr->cur_basic_field_type->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ case CTF_FIELD_TYPE_ID_ENUM:
status = read_basic_int_type_and_call_begin(btr);
break;
- case BT_FIELD_TYPE_ID_FLOAT:
+ case CTF_FIELD_TYPE_ID_FLOAT:
status = read_basic_float_type_and_call_begin(btr);
break;
- case BT_FIELD_TYPE_ID_ENUM:
- status = read_basic_enum_type_and_call_begin(btr);
- break;
- case BT_FIELD_TYPE_ID_STRING:
+ case CTF_FIELD_TYPE_ID_STRING:
status = read_basic_string_type_and_call(btr, true);
break;
default:
- BT_LOGF("Unknown basic field type ID: "
- "btr-addr=%p, ft-addr=%p, ft-id=%s",
- btr, btr->cur_basic_field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(
- btr->cur_basic_field_type)));
abort();
}
BT_ASSERT(btr->cur_basic_field_type);
- switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
- case BT_FIELD_TYPE_ID_INTEGER:
+ switch (btr->cur_basic_field_type->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ case CTF_FIELD_TYPE_ID_ENUM:
status = read_basic_int_type_and_call_continue(btr);
break;
- case BT_FIELD_TYPE_ID_FLOAT:
+ case CTF_FIELD_TYPE_ID_FLOAT:
status = read_basic_float_type_and_call_continue(btr);
break;
- case BT_FIELD_TYPE_ID_ENUM:
- status = read_basic_enum_type_and_call_continue(btr);
- break;
- case BT_FIELD_TYPE_ID_STRING:
+ case CTF_FIELD_TYPE_ID_STRING:
status = read_basic_string_type_and_call(btr, false);
break;
default:
- BT_LOGF("Unknown basic field type ID: "
- "btr-addr=%p, ft-addr=%p, ft-id=%s",
- btr, btr->cur_basic_field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(
- btr->cur_basic_field_type)));
abort();
}
static inline
enum bt_btr_status align_type_state(struct bt_btr *btr,
- struct bt_field_type *field_type, enum btr_state next_state)
+ struct ctf_field_type *field_type, enum btr_state next_state)
{
- int field_alignment;
+ unsigned int field_alignment;
size_t skip_bits;
enum bt_btr_status status = BT_BTR_STATUS_OK;
/* Get field's alignment */
- field_alignment = bt_field_type_get_alignment(field_type);
- if (field_alignment < 0) {
- BT_LOGW("Cannot get field type's alignment: "
- "btr-addr=%p, ft-addr=%p, ft-id=%s",
- btr, field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(field_type)));
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
+ field_alignment = field_type->alignment;
/*
* 0 means "undefined" for variants; what we really want is 1
* (always aligned)
*/
- if (field_alignment == 0) {
- field_alignment = 1;
- }
+ BT_ASSERT(field_alignment >= 1);
/* Compute how many bits we need to skip */
- skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
+ skip_bits = bits_to_skip_to_align_to(btr, (size_t) field_alignment);
/* Nothing to skip? aligned */
if (skip_bits == 0) {
return status;
}
-static inline
-bool is_compound_type(struct bt_field_type *field_type)
-{
- enum bt_field_type_id id = bt_field_type_get_type_id(field_type);
-
- return id == BT_FIELD_TYPE_ID_STRUCT || id == BT_FIELD_TYPE_ID_ARRAY ||
- id == BT_FIELD_TYPE_ID_SEQUENCE || id == BT_FIELD_TYPE_ID_VARIANT;
-}
-
static inline
enum bt_btr_status next_field_state(struct bt_btr *btr)
{
int ret;
struct stack_entry *top;
- struct bt_field_type *next_field_type = NULL;
+ struct ctf_field_type *next_field_type = NULL;
enum bt_btr_status status = BT_BTR_STATUS_OK;
if (stack_empty(btr->stack)) {
}
/* Get next field's type */
- switch (bt_field_type_get_type_id(top->base_type)) {
- case BT_FIELD_TYPE_ID_STRUCT:
- ret = bt_field_type_structure_borrow_field_by_index(
- top->base_type, NULL, &next_field_type,
- top->index);
- if (ret) {
- next_field_type = NULL;
- }
- break;
- case BT_FIELD_TYPE_ID_ARRAY:
- next_field_type =
- bt_field_type_array_borrow_element_field_type(
- top->base_type);
+ switch (top->base_type->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ next_field_type = ctf_field_type_struct_borrow_member_by_index(
+ (void *) top->base_type, (uint64_t) top->index)->ft;
break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- next_field_type =
- bt_field_type_sequence_borrow_element_field_type(
- top->base_type);
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft =
+ (void *) top->base_type;
+
+ next_field_type = array_ft->elem_ft;
break;
- case BT_FIELD_TYPE_ID_VARIANT:
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
/* Variant types are dynamic: query the user, he should know! */
next_field_type =
- btr->user.cbs.query.borrow_variant_field_type(
+ btr->user.cbs.query.borrow_variant_selected_field_type(
top->base_type, btr->user.data);
break;
default:
if (!next_field_type) {
BT_LOGW("Cannot get the field type of the next field: "
- "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
+ "btr-addr=%p, base-ft-addr=%p, base-ft-id=%d, "
"index=%" PRId64,
- btr, top->base_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(top->base_type)),
- top->index);
+ btr, top->base_type, top->base_type->id, top->index);
status = BT_BTR_STATUS_ERROR;
goto end;
}
- if (is_compound_type(next_field_type)) {
+ if (next_field_type->is_compound) {
if (btr->user.cbs.types.compound_begin) {
BT_LOGV("Calling user function (compound, begin).");
status = btr->user.cbs.types.compound_begin(
return status;
}
+BT_HIDDEN
struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data)
{
struct bt_btr *btr;
return btr;
}
+BT_HIDDEN
void bt_btr_destroy(struct bt_btr *btr)
{
if (btr->stack) {
stack_clear(btr->stack);
stitch_reset(btr);
btr->buf.addr = NULL;
- btr->last_bo = BT_BYTE_ORDER_UNKNOWN;
+ btr->last_bo = -1;
}
static
btr->buf.packet_offset += btr->buf.at;
}
+BT_HIDDEN
size_t bt_btr_start(struct bt_btr *btr,
- struct bt_field_type *type, const uint8_t *buf,
+ struct ctf_field_type *type, const uint8_t *buf,
size_t offset, size_t packet_offset, size_t sz,
enum bt_btr_status *status)
{
btr, type, buf, sz, offset, packet_offset);
/* Set root type */
- if (is_compound_type(type)) {
+ if (type->is_compound) {
/* Compound type: push on visit stack */
int stack_ret;
return btr->buf.at;
}
-size_t bt_btr_continue(struct bt_btr *btr,
- const uint8_t *buf, size_t sz,
- enum bt_btr_status *status)
+BT_HIDDEN
+size_t bt_btr_continue(struct bt_btr *btr, const uint8_t *buf, size_t sz,
+ enum bt_btr_status *status)
{
BT_ASSERT(btr);
BT_ASSERT(buf);
update_packet_offset(btr);
return btr->buf.at;
}
+
+BT_HIDDEN
+void bt_btr_set_unsigned_int_cb(struct bt_btr *btr,
+ bt_btr_unsigned_int_cb_func cb)
+{
+ BT_ASSERT(btr);
+ BT_ASSERT(cb);
+ btr->user.cbs.types.unsigned_int = cb;
+}
#include <babeltrace/babeltrace.h>
#include <babeltrace/babeltrace-internal.h>
+#include "../metadata/ctf-meta.h"
+
/**
* @file ctf-btr.h
*
/** Type reader. */
struct bt_btr;
+typedef enum bt_btr_status (* bt_btr_unsigned_int_cb_func)(uint64_t,
+ struct ctf_field_type *, void *);
+
/*
* Type reader user callback functions.
*/
* a compound type begins/ends, or when a basic type is
* completely decoded (along with its value).
*
- * Each function also receives the CTF IR field type associated
+ * Each function also receives the CTF field type associated
* with the call, and user data (registered to the type reader
- * calling them). This field type is a weak reference; the
- * callback function must use bt_field_type_get() to keep
- * its own reference of it.
+ * calling them).
*
- * Actual CTF IR fields are \em not created here; this would be
- * the responsibility of a type reader's user (the provider of
- * those callback functions).
+ * Actual trace IR fields are \em not created here; this would
+ * be the responsibility of a type reader's user (the provider
+ * of those callback functions).
*
* All the type callback functions return one of the following
* values:
* indicate this).
*
* @param value Signed integer value
- * @param type Integer or enumeration type (weak
- * reference)
+ * @param type Integer or enumeration type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* signed_int)(int64_t value,
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
/**
* Called when an unsigned integer type is completely
* indicate this).
*
* @param value Unsigned integer value
- * @param type Integer or enumeration type (weak
- * reference)
+ * @param type Integer or enumeration type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
- enum bt_btr_status (* unsigned_int)(uint64_t value,
- struct bt_field_type *type, void *data);
+ bt_btr_unsigned_int_cb_func unsigned_int;
/**
* Called when a floating point number type is
* completely decoded.
*
* @param value Floating point number value
- * @param type Floating point number type (weak
- * reference)
+ * @param type Floating point number type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* floating_point)(double value,
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
/**
* Called when a string type begins.
* them providing one substring of the complete string
* type's value.
*
- * @param type Beginning string type (weak reference)
+ * @param type Beginning string type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* string_begin)(
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
/**
* Called when a string type's substring is decoded
*
* @param value String value (\em not null-terminated)
* @param len String value length
- * @param type String type (weak reference)
+ * @param type String type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* string)(const char *value,
- size_t len, struct bt_field_type *type,
+ size_t len, struct ctf_field_type *type,
void *data);
/**
* Called when a string type ends.
*
- * @param type Ending string type (weak reference)
+ * @param type Ending string type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* string_end)(
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
/**
* Called when a compound type begins.
* call indicates the selected type of this variant
* type.
*
- * @param type Beginning compound type (weak reference)
+ * @param type Beginning compound type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* compound_begin)(
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
/**
* Called when a compound type ends.
*
- * @param type Ending compound type (weak reference)
+ * @param type Ending compound type
* @param data User data
* @returns #BT_BTR_STATUS_OK or
* #BT_BTR_STATUS_ERROR
*/
enum bt_btr_status (* compound_end)(
- struct bt_field_type *type, void *data);
+ struct ctf_field_type *type, void *data);
} types;
/**
* Called to query the current length of a given sequence
* type.
*
- * @param type Sequence type (weak reference)
+ * @param type Sequence type
* @param data User data
* @returns Sequence length or
* #BT_BTR_STATUS_ERROR on error
*/
- int64_t (* get_sequence_length)(struct bt_field_type *type,
+ int64_t (* get_sequence_length)(struct ctf_field_type *type,
void *data);
/**
* Called to query the current selected type of a given
* variant type.
*
- * @param type Variant type (weak reference)
+ * @param type Variant type
* @param data User data
* @returns Current selected type (owned by
* this) or \c NULL on error
*/
- struct bt_field_type * (* borrow_variant_field_type)(
- struct bt_field_type *type, void *data);
+ struct ctf_field_type * (* borrow_variant_selected_field_type)(
+ struct ctf_field_type *type, void *data);
} query;
};
* @param data User data (passed to user callback functions)
* @returns New binary type reader on success, or \c NULL on error
*/
+BT_HIDDEN
struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data);
/**
*
* @param btr Binary type reader
*/
+BT_HIDDEN
void bt_btr_destroy(struct bt_btr *btr);
/**
* be called next, \em not bt_btr_decode().
*
* @param btr Binary type reader
- * @param type Type to decode (weak reference)
+ * @param type Type to decode
* @param buf Buffer
* @param offset Offset of first bit from \p buf (bits)
* @param packet_offset Offset of \p offset within the CTF
* @param status Returned status (see description above)
* @returns Number of consumed bits
*/
+BT_HIDDEN
size_t bt_btr_start(struct bt_btr *btr,
- struct bt_field_type *type, const uint8_t *buf,
+ struct ctf_field_type *type, const uint8_t *buf,
size_t offset, size_t packet_offset, size_t sz,
enum bt_btr_status *status);
* @param status Returned status (see description above)
* @returns Number of consumed bits
*/
+BT_HIDDEN
size_t bt_btr_continue(struct bt_btr *btr,
const uint8_t *buf, size_t sz,
enum bt_btr_status *status);
+BT_HIDDEN
+void bt_btr_set_unsigned_int_cb(struct bt_btr *btr,
+ bt_btr_unsigned_int_cb_func cb);
+
static inline
const char *bt_btr_status_string(enum bt_btr_status status)
{
decoder.c \
decoder.h \
logging.c \
- logging.h
+ logging.h \
+ ctf-meta.h \
+ ctf-meta-visitors.h \
+ ctf-meta-validate.c \
+ ctf-meta-update-meanings.c \
+ ctf-meta-update-in-ir.c \
+ ctf-meta-update-default-clock-classes.c \
+ ctf-meta-update-text-array-sequence.c \
+ ctf-meta-update-value-storing-indexes.c \
+ ctf-meta-translate.c \
+ ctf-meta-resolve.c
libctf_ast_la_LIBADD = $(UUID_LIBS)
#include <babeltrace/babeltrace-internal.h>
#include "decoder.h"
+#include "ctf-meta.h"
// the parameter name (of the reentrant 'yyparse' function)
// data is a pointer to a 'SParserParam' structure
void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor);
BT_HIDDEN
-struct bt_trace *ctf_visitor_generate_ir_get_trace(
+struct bt_trace *ctf_visitor_generate_ir_get_ir_trace(
+ struct ctf_visitor_generate_ir *visitor);
+
+BT_HIDDEN
+struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
struct ctf_visitor_generate_ir *visitor);
BT_HIDDEN
--- /dev/null
+/*
+ * Copyright 2016-2018 - Philippe Proulx <pproulx@efficios.com>
+ * Copyright 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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-RESOLVE"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/common-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include "ctf-meta-visitors.h"
+
+typedef GPtrArray field_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). `name`
+ * indicates the name of the field type in the upper frame (empty
+ * string for array and sequence field types).
+ */
+struct field_type_stack_frame {
+ struct ctf_field_type *ft;
+ int64_t index;
+};
+
+/*
+ * The current context of the resolving engine.
+ */
+struct resolve_context {
+ struct ctf_trace_class *tc;
+ struct ctf_stream_class *sc;
+ struct ctf_event_class *ec;
+
+ struct {
+ struct ctf_field_type *packet_header;
+ struct ctf_field_type *packet_context;
+ struct ctf_field_type *event_header;
+ struct ctf_field_type *event_common_context;
+ struct ctf_field_type *event_spec_context;
+ struct ctf_field_type *event_payload;
+ } scopes;
+
+ /* Root scope being visited */
+ enum bt_scope root_scope;
+ field_type_stack *field_type_stack;
+ struct ctf_field_type *cur_ft;
+};
+
+/* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
+static const char * const absolute_path_prefixes[] = {
+ [BT_SCOPE_PACKET_HEADER] = "trace.packet.header.",
+ [BT_SCOPE_PACKET_CONTEXT] = "stream.packet.context.",
+ [BT_SCOPE_EVENT_HEADER] = "stream.event.header.",
+ [BT_SCOPE_EVENT_COMMON_CONTEXT] = "stream.event.context.",
+ [BT_SCOPE_EVENT_SPECIFIC_CONTEXT] = "event.context.",
+ [BT_SCOPE_EVENT_PAYLOAD] = "event.fields.",
+};
+
+/* Number of path tokens used for the absolute prefixes */
+static const uint64_t absolute_path_prefix_ptoken_counts[] = {
+ [BT_SCOPE_PACKET_HEADER] = 3,
+ [BT_SCOPE_PACKET_CONTEXT] = 3,
+ [BT_SCOPE_EVENT_HEADER] = 3,
+ [BT_SCOPE_EVENT_COMMON_CONTEXT] = 3,
+ [BT_SCOPE_EVENT_SPECIFIC_CONTEXT] = 2,
+ [BT_SCOPE_EVENT_PAYLOAD] = 2,
+};
+
+static
+void destroy_field_type_stack_frame(struct field_type_stack_frame *frame)
+{
+ if (!frame) {
+ return;
+ }
+
+ g_free(frame);
+}
+
+/*
+ * Creates a type stack.
+ */
+static
+field_type_stack *field_type_stack_create(void)
+{
+ return g_ptr_array_new_with_free_func(
+ (GDestroyNotify) destroy_field_type_stack_frame);
+}
+
+/*
+ * Destroys a type stack.
+ */
+static
+void field_type_stack_destroy(field_type_stack *stack)
+{
+ if (stack) {
+ g_ptr_array_free(stack, TRUE);
+ }
+}
+
+/*
+ * Pushes a field type onto a type stack.
+ */
+static
+int field_type_stack_push(field_type_stack *stack, struct ctf_field_type *ft)
+{
+ int ret = 0;
+ struct field_type_stack_frame *frame = NULL;
+
+ if (!stack || !ft) {
+ BT_LOGE("Invalid parameter: stack or type is NULL.");
+ ret = -1;
+ goto end;
+ }
+
+ frame = g_new0(struct field_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", ft, stack->len);
+ frame->ft = ft;
+ g_ptr_array_add(stack, frame);
+
+end:
+ return ret;
+}
+
+/*
+ * Checks whether or not `stack` is empty.
+ */
+static
+bool field_type_stack_empty(field_type_stack *stack)
+{
+ return stack->len == 0;
+}
+
+/*
+ * Returns the number of frames in `stack`.
+ */
+static
+size_t field_type_stack_size(field_type_stack *stack)
+{
+ return stack->len;
+}
+
+/*
+ * Returns the top frame of `stack`.
+ */
+static
+struct field_type_stack_frame *field_type_stack_peek(field_type_stack *stack)
+{
+ struct field_type_stack_frame *entry = NULL;
+
+ if (!stack || field_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`.
+ */
+static
+struct field_type_stack_frame *field_type_stack_at(field_type_stack *stack,
+ size_t index)
+{
+ struct field_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 field_type_stack_pop(field_type_stack *stack)
+{
+ if (!field_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`.
+ */
+static
+struct ctf_field_type *borrow_type_from_ctx(struct resolve_context *ctx,
+ enum bt_scope scope)
+{
+ switch (scope) {
+ case BT_SCOPE_PACKET_HEADER:
+ return ctx->scopes.packet_header;
+ case BT_SCOPE_PACKET_CONTEXT:
+ return ctx->scopes.packet_context;
+ case BT_SCOPE_EVENT_HEADER:
+ return ctx->scopes.event_header;
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ return ctx->scopes.event_common_context;
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ return ctx->scopes.event_spec_context;
+ case BT_SCOPE_EVENT_PAYLOAD:
+ return ctx->scopes.event_payload;
+ default:
+ abort();
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the CTF scope from a path string. May return -1 if the path
+ * is found to be relative.
+ */
+static
+enum bt_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
+{
+ enum bt_scope scope;
+ enum bt_scope ret = -1;
+ const size_t prefixes_count = sizeof(absolute_path_prefixes) /
+ sizeof(*absolute_path_prefixes);
+
+ for (scope = BT_SCOPE_PACKET_HEADER; scope < BT_SCOPE_PACKET_HEADER +
+ 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_common_scope_string(scope));
+ continue;
+ }
+
+ /* Found it! */
+ ret = scope;
+ BT_LOGV("Found root scope from absolute path: "
+ "path=\"%s\", scope=%s", pathstr,
+ bt_common_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.
+ */
+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_LOGE("Empty path token: path=\"%s\", pos=%u",
+ pathstr, (unsigned 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 `ft`. The index of the source looking for its
+ * target within `ft` is indicated by `src_index`. This can be `INT64_MAX`
+ * if the source is contained in `ft`.
+ *
+ * `field_path` is an output parameter owned by the caller that must be
+ * filled here.
+ */
+static
+int ptokens_to_field_path(GList *ptokens, struct ctf_field_path *field_path,
+ struct ctf_field_type *ft, int64_t src_index)
+{
+ int ret = 0;
+ GList *cur_ptoken = ptokens;
+ bool first_level_done = false;
+
+ /* Locate target */
+ while (cur_ptoken) {
+ int64_t child_index;
+ struct ctf_field_type *child_ft;
+ const char *ft_name = ptoken_get_string(cur_ptoken);
+
+ BT_LOGV("Current path token: token=\"%s\"", ft_name);
+
+ /* Find to which index corresponds the current path token */
+ if (ft->id == CTF_FIELD_TYPE_ID_ARRAY ||
+ ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
+ child_index = -1;
+ } else {
+ child_index =
+ ctf_field_type_compound_get_field_type_index_from_name(
+ ft, ft_name);
+ if (child_index < 0) {
+ /*
+ * Error: field name does not exist or
+ * wrong current type.
+ */
+ BT_LOGV("Cannot get index of field type: "
+ "field-name=\"%s\", "
+ "src-index=%" PRId64 ", "
+ "child-index=%" PRId64 ", "
+ "first-level-done=%d",
+ ft_name, src_index, child_index,
+ first_level_done);
+ ret = -1;
+ goto end;
+ } else if (child_index > src_index &&
+ !first_level_done) {
+ BT_LOGV("Child field type is located after source field type: "
+ "field-name=\"%s\", "
+ "src-index=%" PRId64 ", "
+ "child-index=%" PRId64 ", "
+ "first-level-done=%d",
+ ft_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 = true;
+ }
+
+ /* Create new field path entry */
+ ctf_field_path_append_index(field_path, child_index);
+
+ /* Get child field type */
+ child_ft = ctf_field_type_compound_borrow_field_type_by_index(
+ ft, child_index);
+ BT_ASSERT(child_ft);
+
+ /* Move child type to current type */
+ ft = child_ft;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Converts a known absolute path token list to a field path object
+ * within the resolving context `ctx`.
+ *
+ * `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 ctf_field_path *field_path,
+ struct resolve_context *ctx)
+{
+ int ret = 0;
+ GList *cur_ptoken;
+ struct ctf_field_type *ft;
+
+ /*
+ * Make sure we're not referring to a scope within a translated
+ * object.
+ */
+ switch (field_path->root) {
+ case BT_SCOPE_PACKET_HEADER:
+ if (ctx->tc->is_translated) {
+ BT_LOGE("Trace class is already translated: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ break;
+ case BT_SCOPE_PACKET_CONTEXT:
+ case BT_SCOPE_EVENT_HEADER:
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ if (!ctx->sc) {
+ BT_LOGE("No current stream class: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ if (ctx->sc->is_translated) {
+ BT_LOGE("Stream class is already translated: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ break;
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ case BT_SCOPE_EVENT_PAYLOAD:
+ if (!ctx->ec) {
+ BT_LOGE("No current event class: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ if (ctx->ec->is_translated) {
+ BT_LOGE("Event class is already translated: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ break;
+
+ default:
+ abort();
+ }
+
+ /* Skip absolute path tokens */
+ cur_ptoken = g_list_nth(ptokens,
+ absolute_path_prefix_ptoken_counts[field_path->root]);
+
+ /* Start with root type */
+ ft = borrow_type_from_ctx(ctx, field_path->root);
+ if (!ft) {
+ /* Error: root type is not available */
+ BT_LOGE("Root field type is not available: "
+ "root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ ret = -1;
+ goto end;
+ }
+
+ /* Locate target */
+ ret = ptokens_to_field_path(cur_ptoken, field_path, ft, INT64_MAX);
+
+end:
+ return ret;
+}
+
+/*
+ * Converts a known relative path token list to a field path object
+ * within the resolving context `ctx`.
+ *
+ * `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 ctf_field_path *field_path, struct resolve_context *ctx)
+{
+ int ret = 0;
+ int64_t parent_pos_in_stack;
+ struct ctf_field_path tail_field_path;
+
+ ctf_field_path_init(&tail_field_path);
+ parent_pos_in_stack = field_type_stack_size(ctx->field_type_stack) - 1;
+
+ while (parent_pos_in_stack >= 0) {
+ struct ctf_field_type *parent_type =
+ field_type_stack_at(ctx->field_type_stack,
+ parent_pos_in_stack)->ft;
+ int64_t cur_index = field_type_stack_at(ctx->field_type_stack,
+ parent_pos_in_stack)->index;
+
+ BT_LOGV("Locating target field type from current parent field type: "
+ "parent-pos=%" PRId64 ", parent-ft-addr=%p, "
+ "cur-index=%" PRId64,
+ 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.");
+ ctf_field_path_clear(&tail_field_path);
+ } else {
+ /* Found: stitch tail field path to head field path */
+ uint64_t i = 0;
+ size_t tail_field_path_len =
+ tail_field_path.path->len;
+
+ while (BT_TRUE) {
+ struct ctf_field_type *cur_type =
+ field_type_stack_at(ctx->field_type_stack,
+ i)->ft;
+ int64_t index = field_type_stack_at(
+ ctx->field_type_stack, i)->index;
+
+ if (cur_type == parent_type) {
+ break;
+ }
+
+ ctf_field_path_append_index(field_path,
+ index);
+ i++;
+ }
+
+ for (i = 0; i < tail_field_path_len; i++) {
+ int64_t index =
+ ctf_field_path_borrow_index_by_index(
+ &tail_field_path, i);
+
+ ctf_field_path_append_index(field_path,
+ (int64_t) index);
+ }
+ break;
+ }
+
+ parent_pos_in_stack--;
+ }
+
+ if (parent_pos_in_stack < 0) {
+ /* Not found */
+ ret = -1;
+ }
+
+ ctf_field_path_fini(&tail_field_path);
+ return ret;
+}
+
+/*
+ * Converts a path string to a field path object within the resolving
+ * context `ctx`.
+ */
+static
+int pathstr_to_field_path(const char *pathstr,
+ struct ctf_field_path *field_path, struct resolve_context *ctx)
+{
+ int ret = 0;
+ enum bt_scope root_scope;
+ GList *ptokens = NULL;
+
+ /* Convert path string to path tokens */
+ ptokens = pathstr_to_ptokens(pathstr);
+ if (!ptokens) {
+ BT_LOGE("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 == -1) {
+ /* 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_common_scope_string(field_path->root));
+ ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
+ if (ret) {
+ BT_LOGE("Cannot get relative field path of path string: "
+ "path=\"%s\", start-scope=%s, end-scope=%s",
+ pathstr, bt_common_scope_string(ctx->root_scope),
+ bt_common_scope_string(field_path->root));
+ 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_common_scope_string(field_path->root));
+ ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
+ if (ret) {
+ BT_LOGE("Cannot get absolute field path of path string: "
+ "path=\"%s\", root-scope=%s",
+ pathstr, bt_common_scope_string(root_scope));
+ goto end;
+ }
+ }
+
+ if (BT_LOG_ON_VERBOSE && ret == 0) {
+ GString *field_path_pretty = 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:
+ ptokens_destroy(ptokens);
+ return ret;
+}
+
+/*
+ * Retrieves a field type by following the field path `field_path` in
+ * the resolving context `ctx`.
+ */
+static
+struct ctf_field_type *field_path_to_field_type(
+ struct ctf_field_path *field_path, struct resolve_context *ctx)
+{
+ uint64_t i;
+ struct ctf_field_type *ft;
+
+ /* Start with root type */
+ ft = borrow_type_from_ctx(ctx, field_path->root);
+ if (!ft) {
+ /* Error: root type is not available */
+ BT_LOGE("Root field type is not available: root-scope=%s",
+ bt_common_scope_string(field_path->root));
+ goto end;
+ }
+
+ /* Locate target */
+ for (i = 0; i < field_path->path->len; i++) {
+ struct ctf_field_type *child_ft;
+ int64_t child_index =
+ ctf_field_path_borrow_index_by_index(field_path, i);
+
+ /* Get child field type */
+ child_ft = ctf_field_type_compound_borrow_field_type_by_index(
+ ft, child_index);
+ BT_ASSERT(child_ft);
+
+ /* Move child type to current type */
+ ft = child_ft;
+ }
+
+end:
+ return ft;
+}
+
+/*
+ * Fills the equivalent field path object of the context type stack.
+ */
+static
+void get_ctx_stack_field_path(struct resolve_context *ctx,
+ struct ctf_field_path *field_path)
+{
+ uint64_t i;
+
+ BT_ASSERT(field_path);
+ field_path->root = ctx->root_scope;
+ ctf_field_path_clear(field_path);
+
+ for (i = 0; i < field_type_stack_size(ctx->field_type_stack); i++) {
+ struct field_type_stack_frame *frame =
+ field_type_stack_at(ctx->field_type_stack, i);
+
+ ctf_field_path_append_index(field_path, frame->index);
+ }
+}
+
+/*
+ * Returns the index of the lowest common ancestor of two field path
+ * objects having the same root scope.
+ */
+int64_t get_field_paths_lca_index(struct ctf_field_path *field_path1,
+ struct ctf_field_path *field_path2)
+{
+ int64_t lca_index = 0;
+ uint64_t field_path1_len, field_path2_len;
+
+ if (BT_LOG_ON_VERBOSE) {
+ GString *field_path1_pretty =
+ ctf_field_path_string(field_path1);
+ GString *field_path2_pretty =
+ 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->path->len;
+ field_path2_len = field_path2->path->len;
+
+ while (true) {
+ int64_t target_index, ctx_index;
+
+ if (lca_index == (int64_t) field_path2_len ||
+ lca_index == (int64_t) 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_LOGE("Source field type is an ancestor of target field type or vice versa: "
+ "lca-index=%" PRId64 ", "
+ "field-path-1-len=%" PRIu64 ", "
+ "field-path-2-len=%" PRIu64,
+ lca_index, field_path1_len, field_path2_len);
+ lca_index = -1;
+ break;
+ }
+
+ target_index = ctf_field_path_borrow_index_by_index(field_path1,
+ lca_index);
+ ctx_index = ctf_field_path_borrow_index_by_index(field_path2,
+ lca_index);
+
+ if (target_index != ctx_index) {
+ /* LCA index is the previous */
+ break;
+ }
+
+ lca_index++;
+ }
+
+ BT_LOGV("Found LCA: lca-index=%" PRId64, lca_index);
+ return lca_index;
+}
+
+/*
+ * Validates a target field path.
+ */
+static
+int validate_target_field_path(struct ctf_field_path *target_field_path,
+ struct ctf_field_type *target_ft,
+ struct resolve_context *ctx)
+{
+ int ret = 0;
+ struct ctf_field_path ctx_field_path;
+ uint64_t target_field_path_len = target_field_path->path->len;
+ int64_t lca_index;
+
+ /* Get context field path */
+ ctf_field_path_init(&ctx_field_path);
+ get_ctx_stack_field_path(ctx, &ctx_field_path);
+
+ /*
+ * Make sure the target is not a root.
+ */
+ if (target_field_path_len == 0) {
+ BT_LOGE_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_LOGE("Target field type is located after source field type: "
+ "target-root=%s, source-root=%s",
+ bt_common_scope_string(target_field_path->root),
+ bt_common_scope_string(ctx_field_path.root));
+ ret = -1;
+ goto end;
+ }
+
+ if (target_field_path->root == ctx_field_path.root) {
+ int64_t 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_LOGE_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 = ctf_field_path_borrow_index_by_index(
+ target_field_path, (uint64_t) lca_index);
+ ctx_index = ctf_field_path_borrow_index_by_index(
+ &ctx_field_path, (uint64_t) lca_index);
+
+ if (target_index >= ctx_index) {
+ BT_LOGE("Target field type's index is greater than or equal to source field type's index in LCA: "
+ "lca-index=%" PRId64 ", "
+ "target-index=%" PRId64 ", "
+ "source-index=%" PRId64,
+ lca_index, target_index, ctx_index);
+ ret = -1;
+ goto end;
+ }
+ }
+
+ /*
+ * Make sure the target type has the right type and properties.
+ */
+ switch (ctx->cur_ft->id) {
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ if (target_ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE("Variant field type's tag field type is not an enumeration field type: "
+ "tag-ft-addr=%p, tag-ft-id=%d",
+ target_ft, target_ft->id);
+ ret = -1;
+ goto end;
+ }
+ break;
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_int *int_ft = (void *) target_ft;
+
+ if (target_ft->id != CTF_FIELD_TYPE_ID_INT &&
+ target_ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE("Sequence field type's length field type is not an unsigned integer field type: "
+ "length-ft-addr=%p, length-ft-id=%d",
+ target_ft, target_ft->id);
+ ret = -1;
+ goto end;
+ }
+
+ if (int_ft->is_signed) {
+ BT_LOGE("Sequence field type's length field type is not an unsigned integer field type: "
+ "length-ft-addr=%p, length-ft-id=%d",
+ target_ft, target_ft->id);
+ ret = -1;
+ goto end;
+ }
+ break;
+ }
+ default:
+ abort();
+ }
+
+end:
+ ctf_field_path_fini(&ctx_field_path);
+ return ret;
+}
+
+/*
+ * Resolves a variant or sequence field type `ft`.
+ */
+static
+int resolve_sequence_or_variant_field_type(struct ctf_field_type *ft,
+ struct resolve_context *ctx)
+{
+ int ret = 0;
+ const char *pathstr;
+ struct ctf_field_path target_field_path;
+ struct ctf_field_type *target_ft = NULL;
+ GString *target_field_path_pretty = NULL;
+ const char *target_field_path_pretty_str;
+
+ ctf_field_path_init(&target_field_path);
+
+ /* Get path string */
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_sequence *seq_ft = (void *) ft;
+ pathstr = seq_ft->length_ref->str;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+ pathstr = var_ft->tag_ref->str;
+ break;
+ }
+ default:
+ abort();
+ }
+
+ if (!pathstr) {
+ BT_LOGE_STR("Cannot get path string.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Get target field path out of path string */
+ ret = pathstr_to_field_path(pathstr, &target_field_path, ctx);
+ if (ret) {
+ BT_LOGE("Cannot get target field path for path string: "
+ "path=\"%s\"", pathstr);
+ goto end;
+ }
+
+ target_field_path_pretty = 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_ft = field_path_to_field_type(&target_field_path, ctx);
+ if (!target_ft) {
+ BT_LOGE("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_ft, ctx);
+ if (ret) {
+ BT_LOGE("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 (ft->id) {
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_sequence *seq_ft = (void *) ft;
+
+ ctf_field_path_copy_content(&seq_ft->length_path,
+ &target_field_path);
+ seq_ft->length_ft = (void *) target_ft;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ ctf_field_path_copy_content(&var_ft->tag_path,
+ &target_field_path);
+ ctf_field_type_variant_set_tag_field_type(var_ft,
+ (void *) target_ft);
+ break;
+ }
+ default:
+ abort();
+ }
+
+end:
+ if (target_field_path_pretty) {
+ g_string_free(target_field_path_pretty, TRUE);
+ }
+
+ ctf_field_path_fini(&target_field_path);
+ return ret;
+}
+
+/*
+ * Resolves a field type `ft`.
+ */
+static
+int resolve_field_type(struct ctf_field_type *ft, struct resolve_context *ctx)
+{
+ int ret = 0;
+
+ if (!ft) {
+ /* Type is not available; still valid */
+ goto end;
+ }
+
+ ctx->cur_ft = ft;
+
+ /* Resolve sequence/variant field type */
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ ret = resolve_sequence_or_variant_field_type(ft, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve sequence field type's length or variant field type's tag: "
+ "ret=%d, ft-addr=%p", ret, ft);
+ goto end;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ /* Recurse into compound types */
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ {
+ uint64_t i;
+ uint64_t field_count =
+ ctf_field_type_compound_get_field_type_count(ft);
+
+ ret = field_type_stack_push(ctx->field_type_stack, ft);
+ if (ret) {
+ BT_LOGE("Cannot push field type on context's stack: "
+ "ft-addr=%p", ft);
+ goto end;
+ }
+
+ for (i = 0; i < field_count; i++) {
+ struct ctf_field_type *child_ft =
+ ctf_field_type_compound_borrow_field_type_by_index(
+ ft, i);
+
+ BT_ASSERT(child_ft);
+
+ if (ft->id == CTF_FIELD_TYPE_ID_ARRAY||
+ ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
+ field_type_stack_peek(
+ ctx->field_type_stack)->index = -1;
+ } else {
+ field_type_stack_peek(
+ ctx->field_type_stack)->index =
+ (int64_t) i;
+ }
+
+ BT_LOGV("Resolving field type's child field type: "
+ "parent-ft-addr=%p, child-ft-addr=%p, "
+ "index=%" PRIu64 ", count=%" PRIu64,
+ ft, child_ft, i, field_count);
+ ret = resolve_field_type(child_ft, ctx);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ field_type_stack_pop(ctx->field_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_scope root_scope, struct resolve_context *ctx)
+{
+ int ret;
+
+ BT_ASSERT(field_type_stack_size(ctx->field_type_stack) == 0);
+ ctx->root_scope = root_scope;
+ ret = resolve_field_type(borrow_type_from_ctx(ctx, root_scope), ctx);
+ ctx->root_scope = -1;
+ return ret;
+}
+
+static
+int resolve_event_class_field_types(struct resolve_context *ctx,
+ struct ctf_event_class *ec)
+{
+ int ret = 0;
+
+ BT_ASSERT(!ctx->scopes.event_spec_context);
+ BT_ASSERT(!ctx->scopes.event_payload);
+
+ if (ec->is_translated) {
+ goto end;
+ }
+
+ ctx->ec = ec;
+ ctx->scopes.event_spec_context = ec->spec_context_ft;
+ ret = resolve_root_type(BT_SCOPE_EVENT_COMMON_CONTEXT, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve event specific context field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ ctx->scopes.event_payload = ec->payload_ft;
+ ret = resolve_root_type(BT_SCOPE_EVENT_PAYLOAD, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve event payload field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+end:
+ ctx->scopes.event_spec_context = NULL;
+ ctx->scopes.event_payload = NULL;
+ ctx->ec = NULL;
+ return ret;
+}
+
+static
+int resolve_stream_class_field_types(struct resolve_context *ctx,
+ struct ctf_stream_class *sc)
+{
+ int ret = 0;
+ uint64_t i;
+
+ BT_ASSERT(!ctx->scopes.packet_context);
+ BT_ASSERT(!ctx->scopes.event_header);
+ BT_ASSERT(!ctx->scopes.event_common_context);
+ ctx->sc = sc;
+
+ if (!sc->is_translated) {
+ ctx->scopes.packet_context = sc->packet_context_ft;
+ ret = resolve_root_type(BT_SCOPE_PACKET_CONTEXT, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve packet context field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ ctx->scopes.event_header = sc->event_header_ft;
+ ret = resolve_root_type(BT_SCOPE_EVENT_HEADER, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve event header field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ ctx->scopes.event_common_context = sc->event_common_context_ft;
+ ret = resolve_root_type(BT_SCOPE_EVENT_SPECIFIC_CONTEXT, ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve event common context field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+ }
+
+ ctx->scopes.packet_context = sc->packet_context_ft;
+ ctx->scopes.event_header = sc->event_header_ft;
+ ctx->scopes.event_common_context = sc->event_common_context_ft;
+
+ for (i = 0; i < sc->event_classes->len; i++) {
+ struct ctf_event_class *ec = sc->event_classes->pdata[i];
+
+ ret = resolve_event_class_field_types(ctx, ec);
+ if (ret) {
+ BT_LOGE("Cannot resolve event class's field types: "
+ "ec-id=%" PRIu64 ", ec-name=\"%s\"",
+ ec->id, ec->name->str);
+ goto end;
+ }
+ }
+
+end:
+ ctx->scopes.packet_context = NULL;
+ ctx->scopes.event_header = NULL;
+ ctx->scopes.event_common_context = NULL;
+ ctx->sc = NULL;
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_resolve_field_types(struct ctf_trace_class *tc)
+{
+ int ret = 0;
+ uint64_t i;
+ struct resolve_context ctx = {
+ .tc = tc,
+ .sc = NULL,
+ .ec = NULL,
+ .scopes = {
+ .packet_header = tc->packet_header_ft,
+ .packet_context = NULL,
+ .event_header = NULL,
+ .event_common_context = NULL,
+ .event_spec_context = NULL,
+ .event_payload = NULL,
+ },
+ .root_scope = BT_SCOPE_PACKET_HEADER,
+ .cur_ft = NULL,
+ };
+
+ /* Initialize type stack */
+ ctx.field_type_stack = field_type_stack_create();
+ if (!ctx.field_type_stack) {
+ BT_LOGE_STR("Cannot create field type stack.");
+ ret = -1;
+ goto end;
+ }
+
+ if (!tc->is_translated) {
+ ctx.scopes.packet_header = tc->packet_header_ft;
+ ret = resolve_root_type(BT_SCOPE_PACKET_HEADER, &ctx);
+ if (ret) {
+ BT_LOGE("Cannot resolve packet header field type: "
+ "ret=%d", ret);
+ goto end;
+ }
+ }
+
+ ctx.scopes.packet_header = tc->packet_header_ft;
+
+ for (i = 0; i < tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc = tc->stream_classes->pdata[i];
+
+ ret = resolve_stream_class_field_types(&ctx, sc);
+ if (ret) {
+ BT_LOGE("Cannot resolve stream class's field types: "
+ "sc-id=%" PRIu64, sc->id);
+ goto end;
+ }
+ }
+
+end:
+ field_type_stack_destroy(ctx.field_type_stack);
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-TRANSLATE"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static inline
+struct bt_field_type *ctf_field_type_to_ir(struct ctf_field_type *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec);
+
+static inline
+void ctf_field_type_int_set_props(struct ctf_field_type_int *ft,
+ struct bt_field_type *ir_ft)
+{
+ int ret;
+
+ ret = bt_field_type_integer_set_field_value_range(ir_ft, ft->base.size);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_integer_set_preferred_display_base(ir_ft,
+ ft->disp_base);
+ BT_ASSERT(ret == 0);
+}
+
+static inline
+struct bt_field_type *ctf_field_type_int_to_ir(struct ctf_field_type_int *ft)
+{
+ struct bt_field_type *ir_ft;
+
+ if (ft->is_signed) {
+ ir_ft = bt_field_type_signed_integer_create();
+ } else {
+ ir_ft = bt_field_type_unsigned_integer_create();
+ }
+
+ BT_ASSERT(ir_ft);
+ ctf_field_type_int_set_props(ft, ir_ft);
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_enum_to_ir(struct ctf_field_type_enum *ft)
+{
+ int ret;
+ struct bt_field_type *ir_ft;
+ uint64_t i;
+
+ if (ft->base.is_signed) {
+ ir_ft = bt_field_type_signed_enumeration_create();
+ } else {
+ ir_ft = bt_field_type_unsigned_enumeration_create();
+ }
+
+ BT_ASSERT(ir_ft);
+ ctf_field_type_int_set_props((void *) ft, ir_ft);
+
+ for (i = 0; i < ft->mappings->len; i++) {
+ struct ctf_field_type_enum_mapping *mapping =
+ ctf_field_type_enum_borrow_mapping_by_index(ft, i);
+
+ if (ft->base.is_signed) {
+ ret = bt_field_type_signed_enumeration_map_range(
+ ir_ft, mapping->label->str,
+ mapping->range.lower.i, mapping->range.upper.i);
+ } else {
+ ret = bt_field_type_unsigned_enumeration_map_range(
+ ir_ft, mapping->label->str,
+ mapping->range.lower.u, mapping->range.upper.u);
+ }
+
+ BT_ASSERT(ret == 0);
+ }
+
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_float_to_ir(
+ struct ctf_field_type_float *ft)
+{
+ struct bt_field_type *ir_ft;
+ int ret;
+
+ ir_ft = bt_field_type_real_create();
+ BT_ASSERT(ir_ft);
+
+ if (ft->base.size == 32) {
+ ret = bt_field_type_real_set_is_single_precision(ir_ft,
+ BT_TRUE);
+ BT_ASSERT(ret == 0);
+ }
+
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_string_to_ir(
+ struct ctf_field_type_string *ft)
+{
+ struct bt_field_type *ir_ft = bt_field_type_string_create();
+
+ BT_ASSERT(ir_ft);
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_struct_to_ir(
+ struct ctf_field_type_struct *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ int ret;
+ struct bt_field_type *ir_ft = bt_field_type_structure_create();
+ uint64_t i;
+
+ BT_ASSERT(ir_ft);
+
+ for (i = 0; i < ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(ft, i);
+ struct bt_field_type *member_ir_ft;
+
+ if (!named_ft->ft->in_ir) {
+ continue;
+ }
+
+ member_ir_ft = ctf_field_type_to_ir(named_ft->ft, tc, sc, ec);
+ BT_ASSERT(member_ir_ft);
+ ret = bt_field_type_structure_append_member(ir_ft,
+ named_ft->name->str, member_ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(member_ir_ft);
+ }
+
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *borrow_ir_ft_from_field_path(
+ struct ctf_field_path *field_path,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ struct bt_field_type *ir_ft = NULL;
+ struct ctf_field_type *ft = ctf_field_path_borrow_field_type(
+ field_path, tc, sc, ec);
+
+ BT_ASSERT(ft);
+
+ if (ft->in_ir) {
+ ir_ft = ft->ir_ft;
+ }
+
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_variant_to_ir(
+ struct ctf_field_type_variant *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ int ret;
+ struct bt_field_type *ir_ft = bt_field_type_variant_create();
+ uint64_t i;
+
+ BT_ASSERT(ir_ft);
+ ret = bt_field_type_variant_set_selector_field_type(ir_ft,
+ borrow_ir_ft_from_field_path(&ft->tag_path, tc, sc, ec));
+ BT_ASSERT(ret == 0);
+
+ for (i = 0; i < ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(ft, i);
+ struct bt_field_type *option_ir_ft;
+
+ BT_ASSERT(named_ft->ft->in_ir);
+ option_ir_ft = ctf_field_type_to_ir(named_ft->ft, tc, sc, ec);
+ BT_ASSERT(option_ir_ft);
+ ret = bt_field_type_variant_append_option(ir_ft,
+ named_ft->name->str, option_ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(option_ir_ft);
+ }
+
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_array_to_ir(
+ struct ctf_field_type_array *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ struct bt_field_type *ir_ft;
+ struct bt_field_type *elem_ir_ft;
+
+ if (ft->base.is_text) {
+ ir_ft = bt_field_type_string_create();
+ BT_ASSERT(ir_ft);
+ goto end;
+ }
+
+ elem_ir_ft = ctf_field_type_to_ir(ft->base.elem_ft, tc, sc, ec);
+ BT_ASSERT(elem_ir_ft);
+ ir_ft = bt_field_type_static_array_create(elem_ir_ft, ft->length);
+ BT_ASSERT(ir_ft);
+ bt_put(elem_ir_ft);
+
+end:
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_sequence_to_ir(
+ struct ctf_field_type_sequence *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ int ret;
+ struct bt_field_type *ir_ft;
+ struct bt_field_type *elem_ir_ft;
+
+ if (ft->base.is_text) {
+ ir_ft = bt_field_type_string_create();
+ BT_ASSERT(ir_ft);
+ goto end;
+ }
+
+ elem_ir_ft = ctf_field_type_to_ir(ft->base.elem_ft, tc, sc, ec);
+ BT_ASSERT(elem_ir_ft);
+ ir_ft = bt_field_type_dynamic_array_create(elem_ir_ft);
+ BT_ASSERT(ir_ft);
+ bt_put(elem_ir_ft);
+ BT_ASSERT(ir_ft);
+ ret = bt_field_type_dynamic_array_set_length_field_type(ir_ft,
+ borrow_ir_ft_from_field_path(&ft->length_path, tc, sc, ec));
+ BT_ASSERT(ret == 0);
+
+end:
+ return ir_ft;
+}
+
+static inline
+struct bt_field_type *ctf_field_type_to_ir(struct ctf_field_type *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ struct bt_field_type *ir_ft = NULL;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(ft->in_ir);
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ ir_ft = ctf_field_type_int_to_ir((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_ENUM:
+ ir_ft = ctf_field_type_enum_to_ir((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_FLOAT:
+ ir_ft = ctf_field_type_float_to_ir((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRING:
+ ir_ft = ctf_field_type_string_to_ir((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ ir_ft = ctf_field_type_struct_to_ir((void *) ft, tc, sc, ec);
+ break;
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ ir_ft = ctf_field_type_array_to_ir((void *) ft, tc, sc, ec);
+ break;
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ ir_ft = ctf_field_type_sequence_to_ir((void *) ft, tc, sc, ec);
+ break;
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ ir_ft = ctf_field_type_variant_to_ir((void *) ft, tc, sc, ec);
+ break;
+ default:
+ abort();
+ }
+
+ ft->ir_ft = ir_ft;
+ return ir_ft;
+}
+
+static inline
+bool ctf_field_type_struct_has_immediate_member_in_ir(
+ struct ctf_field_type_struct *ft)
+{
+ uint64_t i;
+ bool has_immediate_member_in_ir = false;
+
+ for (i = 0; i < ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(ft, i);
+
+ if (named_ft->ft->in_ir) {
+ has_immediate_member_in_ir = true;
+ goto end;
+ }
+ }
+
+end:
+ return has_immediate_member_in_ir;
+}
+
+static inline
+struct bt_field_type *scope_ctf_field_type_to_ir(struct ctf_field_type *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ struct bt_field_type *ir_ft = NULL;
+
+ if (!ft) {
+ goto end;
+ }
+
+ BT_ASSERT(ft->id == CTF_FIELD_TYPE_ID_STRUCT);
+
+ if (!ctf_field_type_struct_has_immediate_member_in_ir((void *) ft)) {
+ /*
+ * Nothing for IR in this scope: typical for packet
+ * header, packet context, and event header.
+ */
+ goto end;
+ }
+
+ ir_ft = ctf_field_type_to_ir(ft, tc, sc, ec);
+
+end:
+ return ir_ft;
+}
+
+static inline
+struct ctf_field_type_int *borrow_named_int_field_type(
+ struct ctf_field_type_struct *struct_ft, const char *name)
+{
+ struct ctf_named_field_type *named_ft = NULL;
+ struct ctf_field_type_int *int_ft = NULL;
+
+ if (!struct_ft) {
+ goto end;
+ }
+
+ named_ft = ctf_field_type_struct_borrow_member_by_name(struct_ft, name);
+ if (!named_ft) {
+ goto end;
+ }
+
+ if (named_ft->ft->id != CTF_FIELD_TYPE_ID_INT &&
+ named_ft->ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ goto end;
+ }
+
+ int_ft = (void *) named_ft->ft;
+
+end:
+ return int_ft;
+}
+
+static inline
+struct bt_event_class *ctf_event_class_to_ir(struct ctf_event_class *ec,
+ struct bt_stream_class *ir_sc, struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc)
+{
+ int ret;
+ struct bt_event_class *ir_ec = NULL;
+
+ if (ec->is_translated) {
+ ir_ec = bt_stream_class_borrow_event_class_by_id(
+ ir_sc, ec->id);
+ BT_ASSERT(ir_ec);
+ goto end;
+ }
+
+ ir_ec = bt_event_class_create_with_id(ir_sc, ec->id);
+ BT_ASSERT(ir_ec);
+ bt_put(ir_ec);
+
+ if (ec->spec_context_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ ec->spec_context_ft, tc, sc, ec);
+
+ if (ir_ft) {
+ ret = bt_event_class_set_specific_context_field_type(
+ ir_ec, ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ if (ec->payload_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ ec->payload_ft, tc, sc, ec);
+
+ if (ir_ft) {
+ ret = bt_event_class_set_payload_field_type(ir_ec,
+ ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ if (ec->name->len > 0) {
+ ret = bt_event_class_set_name(ir_ec, ec->name->str);
+ BT_ASSERT(ret == 0);
+ }
+
+ if (ec->emf_uri->len > 0) {
+ ret = bt_event_class_set_emf_uri(ir_ec, ec->emf_uri->str);
+ BT_ASSERT(ret == 0);
+ }
+
+ if (ec->log_level != -1) {
+ ret = bt_event_class_set_log_level(ir_ec, ec->log_level);
+ BT_ASSERT(ret == 0);
+ }
+
+ ec->is_translated = true;
+ ec->ir_ec = ir_ec;
+
+end:
+ return ir_ec;
+}
+
+
+static inline
+struct bt_stream_class *ctf_stream_class_to_ir(struct ctf_stream_class *sc,
+ struct bt_trace *ir_trace, struct ctf_trace_class *tc)
+{
+ int ret;
+ struct bt_stream_class *ir_sc = NULL;
+ struct ctf_field_type_int *int_ft;
+
+ if (sc->is_translated) {
+ ir_sc = bt_trace_borrow_stream_class_by_id(ir_trace, sc->id);
+ BT_ASSERT(ir_sc);
+ goto end;
+ }
+
+ ir_sc = bt_stream_class_create_with_id(ir_trace, sc->id);
+ BT_ASSERT(ir_sc);
+ bt_put(ir_sc);
+
+ if (sc->packet_context_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ sc->packet_context_ft, tc, sc, NULL);
+
+ if (ir_ft) {
+ ret = bt_stream_class_set_packet_context_field_type(
+ ir_sc, ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ if (sc->event_header_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ sc->event_header_ft, tc, sc, NULL);
+
+ if (ir_ft) {
+ ret = bt_stream_class_set_event_header_field_type(ir_sc,
+ ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ if (sc->event_common_context_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ sc->event_common_context_ft, tc, sc, NULL);
+
+ if (ir_ft) {
+ ret = bt_stream_class_set_event_common_context_field_type(
+ ir_sc, ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ ret = bt_stream_class_set_assigns_automatic_event_class_id(ir_sc,
+ BT_FALSE);
+ BT_ASSERT(ret == 0);
+ ret = bt_stream_class_set_assigns_automatic_stream_id(ir_sc, BT_FALSE);
+ BT_ASSERT(ret == 0);
+
+ if (sc->default_clock_class) {
+ ret = bt_stream_class_set_default_clock_class(ir_sc,
+ sc->default_clock_class);
+ BT_ASSERT(ret == 0);
+ }
+
+ int_ft = borrow_named_int_field_type((void *) sc->packet_context_ft,
+ "events_discarded");
+ if (int_ft) {
+ if (int_ft->meaning == CTF_FIELD_TYPE_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT) {
+ ret = bt_stream_class_set_packets_have_discarded_event_counter_snapshot(
+ ir_sc, BT_TRUE);
+ BT_ASSERT(ret == 0);
+ }
+ }
+
+ int_ft = borrow_named_int_field_type((void *) sc->packet_context_ft,
+ "packet_seq_num");
+ if (int_ft) {
+ if (int_ft->meaning == CTF_FIELD_TYPE_MEANING_PACKET_COUNTER_SNAPSHOT) {
+ ret = bt_stream_class_set_packets_have_packet_counter_snapshot(
+ ir_sc, BT_TRUE);
+ BT_ASSERT(ret == 0);
+ }
+ }
+
+ int_ft = borrow_named_int_field_type((void *) sc->packet_context_ft,
+ "timestamp_begin");
+ if (int_ft) {
+ if (int_ft->meaning == CTF_FIELD_TYPE_MEANING_PACKET_BEGINNING_TIME) {
+ ret = bt_stream_class_set_packets_have_default_beginning_clock_value(
+ ir_sc, BT_TRUE);
+ BT_ASSERT(ret == 0);
+ }
+ }
+
+ int_ft = borrow_named_int_field_type((void *) sc->packet_context_ft,
+ "timestamp_end");
+ if (int_ft) {
+ if (int_ft->meaning == CTF_FIELD_TYPE_MEANING_PACKET_END_TIME) {
+ ret = bt_stream_class_set_packets_have_default_end_clock_value(
+ ir_sc, BT_TRUE);
+ BT_ASSERT(ret == 0);
+ }
+ }
+
+ sc->is_translated = true;
+ sc->ir_sc = ir_sc;
+
+end:
+ return ir_sc;
+}
+
+static inline
+int ctf_trace_class_to_ir(struct bt_trace *ir_trace,
+ struct ctf_trace_class *tc)
+{
+ int ret = 0;
+ uint64_t i;
+
+ if (tc->is_translated) {
+ goto end;
+ }
+
+ if (tc->packet_header_ft) {
+ struct bt_field_type *ir_ft = scope_ctf_field_type_to_ir(
+ tc->packet_header_ft, tc, NULL, NULL);
+
+ if (ir_ft) {
+ ret = bt_trace_set_packet_header_field_type(ir_trace,
+ ir_ft);
+ BT_ASSERT(ret == 0);
+ bt_put(ir_ft);
+ }
+ }
+
+ if (tc->name->len > 0) {
+ ret = bt_trace_set_name(ir_trace, tc->name->str);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ if (tc->is_uuid_set) {
+ ret = bt_trace_set_uuid(ir_trace, tc->uuid);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ for (i = 0; i < tc->env_entries->len; i++) {
+ struct ctf_trace_class_env_entry *env_entry =
+ ctf_trace_class_borrow_env_entry_by_index(tc, i);
+
+ switch (env_entry->type) {
+ case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT:
+ ret = bt_trace_set_environment_entry_integer(
+ ir_trace, env_entry->name->str,
+ env_entry->value.i);
+ break;
+ case CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR:
+ ret = bt_trace_set_environment_entry_string(
+ ir_trace, env_entry->name->str,
+ env_entry->value.str->str);
+ break;
+ default:
+ abort();
+ }
+
+ if (ret) {
+ goto end;
+ }
+ }
+
+ ret = bt_trace_set_assigns_automatic_stream_class_id(ir_trace,
+ BT_FALSE);
+ if (ret) {
+ goto end;
+ }
+
+ tc->is_translated = true;
+ tc->ir_tc = ir_trace;
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_translate(struct bt_trace *ir_trace,
+ struct ctf_trace_class *tc)
+{
+ int ret = 0;
+ uint64_t i;
+
+ ret = ctf_trace_class_to_ir(ir_trace, tc);
+ if (ret) {
+ goto end;
+ }
+
+ for (i = 0; i < tc->stream_classes->len; i++) {
+ uint64_t j;
+ struct ctf_stream_class *sc = tc->stream_classes->pdata[i];
+ struct bt_stream_class *ir_sc;
+
+ ir_sc = ctf_stream_class_to_ir(sc, ir_trace, tc);
+ if (!ir_sc) {
+ ret = -1;
+ goto end;
+ }
+
+ for (j = 0; j < sc->event_classes->len; j++) {
+ struct ctf_event_class *ec = sc->event_classes->pdata[j];
+ struct bt_event_class *ir_ec;
+
+ ir_ec = ctf_event_class_to_ir(ec, ir_sc, tc, sc);
+ if (!ir_ec) {
+ ret = -1;
+ goto end;
+ }
+ }
+ }
+
+end:
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-DEF-CC"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static inline
+int find_mapped_clock_class(struct ctf_field_type *ft,
+ struct bt_clock_class **clock_class)
+{
+ int ret = 0;
+ uint64_t i;
+
+ if (!ft) {
+ goto end;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ case CTF_FIELD_TYPE_ID_ENUM:
+ {
+ struct ctf_field_type_int *int_ft = (void *) ft;
+
+ if (int_ft->mapped_clock_class) {
+ if (*clock_class && *clock_class !=
+ int_ft->mapped_clock_class) {
+ BT_LOGE("Stream class contains more than one "
+ "clock class: expected-cc-name=\"%s\", "
+ "other-cc-name=\"%s\"",
+ bt_clock_class_get_name(*clock_class),
+ bt_clock_class_get_name(int_ft->mapped_clock_class));
+ ret = -1;
+ goto end;
+ }
+
+ *clock_class = int_ft->mapped_clock_class;
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ for (i = 0; i < struct_ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ ret = find_mapped_clock_class(named_ft->ft,
+ clock_class);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ for (i = 0; i < var_ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ ret = find_mapped_clock_class(named_ft->ft,
+ clock_class);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ ret = find_mapped_clock_class(array_ft->elem_ft, clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+static inline
+int update_stream_class_default_clock_class(
+ struct ctf_stream_class *stream_class)
+{
+ int ret = 0;
+ struct bt_clock_class *clock_class = stream_class->default_clock_class;
+ uint64_t i;
+
+ ret = find_mapped_clock_class(stream_class->packet_context_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ ret = find_mapped_clock_class(stream_class->event_header_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ ret = find_mapped_clock_class(stream_class->event_common_context_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ for (i = 0; i < stream_class->event_classes->len; i++) {
+ struct ctf_event_class *event_class =
+ stream_class->event_classes->pdata[i];
+
+ ret = find_mapped_clock_class(event_class->spec_context_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ ret = find_mapped_clock_class(event_class->payload_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ if (!stream_class->default_clock_class) {
+ stream_class->default_clock_class = bt_get(clock_class);
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_update_default_clock_classes(struct ctf_trace_class *ctf_tc)
+{
+ uint64_t i;
+ int ret = 0;
+ struct bt_clock_class *clock_class = NULL;
+
+ ret = find_mapped_clock_class(ctf_tc->packet_header_ft,
+ &clock_class);
+ if (ret) {
+ goto end;
+ }
+
+ if (clock_class) {
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc =
+ ctf_tc->stream_classes->pdata[i];
+
+ ret = update_stream_class_default_clock_class(
+ ctf_tc->stream_classes->pdata[i]);
+ if (ret) {
+ BT_LOGE("Stream class contains more than one "
+ "clock class: stream-class-id=%" PRIu64,
+ sc->id);
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-IN-IR"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compat/glib-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static
+void update_field_type_in_ir(struct ctf_field_type *ft,
+ GHashTable *ft_dependents)
+{
+ int64_t i;
+
+ if (!ft) {
+ goto end;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ case CTF_FIELD_TYPE_ID_ENUM:
+ {
+ struct ctf_field_type_int *int_ft = (void *) ft;
+
+ if (int_ft->mapped_clock_class ||
+ int_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE ||
+ bt_g_hash_table_contains(ft_dependents, ft)) {
+ /*
+ * Field type does not update a clock, has no
+ * special meaning, and no sequence/variant
+ * field type which is part of IR depends on it.
+ */
+ ft->in_ir = true;
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ /* Reverse order */
+ for (i = (int64_t) struct_ft->members->len - 1; i >= 0; i--) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ update_field_type_in_ir(named_ft->ft, ft_dependents);
+
+ if (named_ft->ft->in_ir) {
+ /* At least one member is part of IR */
+ ft->in_ir = true;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_named_field_type *named_ft;
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ /*
+ * Reverse order, although it is not important for this
+ * loop because a field type within a variant field
+ * type's option cannot depend on a field type in
+ * another option of the same variant field type.
+ */
+ for (i = (int64_t) var_ft->options->len - 1; i >= 0; i--) {
+ named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ update_field_type_in_ir(named_ft->ft, ft_dependents);
+
+ if (named_ft->ft->in_ir) {
+ /* At least one option is part of IR */
+ ft->in_ir = true;
+ }
+ }
+
+ if (ft->in_ir) {
+ /*
+ * At least one option will make it to IR. In
+ * this case, make all options part of IR
+ * because the variant's tag could still select
+ * (dynamically) a removed option. This can mean
+ * having an empty structure as an option, for
+ * example, but at least all the options are
+ * selectable.
+ */
+ for (i = 0; i < var_ft->options->len; i++) {
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i)->ft->in_ir = true;
+ }
+
+ /*
+ * This variant field type is part of IR and
+ * depends on a tag field type (which must also
+ * be part of IR).
+ */
+ g_hash_table_insert(ft_dependents, var_ft->tag_ft,
+ var_ft->tag_ft);
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ update_field_type_in_ir(array_ft->elem_ft, ft_dependents);
+ ft->in_ir = array_ft->elem_ft->in_ir;
+
+ if (ft->id == CTF_FIELD_TYPE_ID_ARRAY) {
+ struct ctf_field_type_array *arr_ft = (void *) ft;
+
+ assert(arr_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE ||
+ arr_ft->meaning == CTF_FIELD_TYPE_MEANING_UUID);
+
+ /*
+ * UUID field type: nothing depends on this, so
+ * it's not part of IR.
+ */
+ if (arr_ft->meaning == CTF_FIELD_TYPE_MEANING_UUID) {
+ ft->in_ir = false;
+ array_ft->elem_ft->in_ir = false;
+ }
+ } else if (ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
+ if (ft->in_ir) {
+ struct ctf_field_type_sequence *seq_ft = (void *) ft;
+
+ /*
+ * This sequence field type is part of
+ * IR and depends on a length field type
+ * (which must also be part of IR).
+ */
+ g_hash_table_insert(ft_dependents,
+ seq_ft->length_ft, seq_ft->length_ft);
+ }
+ }
+
+ break;
+ }
+ default:
+ ft->in_ir = true;
+ break;
+ }
+
+end:
+ return;
+}
+
+/*
+ * Scopes and field types are processed in reverse order because we need
+ * to know if a given integer field type has dependents (sequence or
+ * variant field types) when we reach it. Dependents can only be located
+ * after the length/tag field type in the metadata tree.
+ */
+BT_HIDDEN
+int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc)
+{
+ int ret = 0;
+ uint64_t i;
+
+ GHashTable *ft_dependents = g_hash_table_new(g_direct_hash,
+ g_direct_equal);
+
+ BT_ASSERT(ft_dependents);
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
+ uint64_t j;
+
+ for (j = 0; j < sc->event_classes->len; j++) {
+ struct ctf_event_class *ec = sc->event_classes->pdata[j];
+
+ if (ec->is_translated) {
+ continue;
+ }
+
+ update_field_type_in_ir(ec->payload_ft, ft_dependents);
+ update_field_type_in_ir(ec->spec_context_ft,
+ ft_dependents);
+ }
+
+ if (!sc->is_translated) {
+ update_field_type_in_ir(sc->event_common_context_ft,
+ ft_dependents);
+ update_field_type_in_ir(sc->event_header_ft,
+ ft_dependents);
+ update_field_type_in_ir(sc->packet_context_ft,
+ ft_dependents);
+ }
+ }
+
+ if (!ctf_tc->is_translated) {
+ update_field_type_in_ir(ctf_tc->packet_header_ft,
+ ft_dependents);
+ }
+
+ g_hash_table_destroy(ft_dependents);
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-MEANINGS"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static
+int set_int_field_type_meaning_by_name(struct ctf_field_type *ft,
+ const char *field_name, const char *id_name,
+ enum ctf_field_type_meaning meaning)
+{
+ int ret = 0;
+ uint64_t i;
+
+ if (!ft) {
+ goto end;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ case CTF_FIELD_TYPE_ID_ENUM:
+ {
+ struct ctf_field_type_int *int_ft = (void *) ft;
+
+ if (field_name && strcmp(field_name, id_name) == 0) {
+ int_ft->meaning = meaning;
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ for (i = 0; i < struct_ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ ret = set_int_field_type_meaning_by_name(named_ft->ft,
+ named_ft->name->str, id_name, meaning);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ for (i = 0; i < var_ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ ret = set_int_field_type_meaning_by_name(named_ft->ft,
+ NULL, id_name, meaning);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ ret = set_int_field_type_meaning_by_name(array_ft->elem_ft,
+ NULL, id_name, meaning);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+static
+int update_stream_class_meanings(struct ctf_stream_class *sc)
+{
+ int ret = 0;
+ struct ctf_field_type_int *int_ft;
+ uint64_t i;
+
+ if (!sc->is_translated) {
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "timestamp_begin");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_PACKET_BEGINNING_TIME;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "timestamp_end");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_PACKET_END_TIME;
+
+ /*
+ * Remove mapped clock class to avoid updating
+ * the clock immediately when decoding.
+ */
+ int_ft->mapped_clock_class = NULL;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "events_discarded");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "packet_seq_num");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_PACKET_COUNTER_SNAPSHOT;
+
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "packet_size");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_EXP_PACKET_TOTAL_SIZE;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) sc->packet_context_ft, "content_size");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_EXP_PACKET_CONTENT_SIZE;
+ }
+
+ ret = set_int_field_type_meaning_by_name(
+ sc->event_header_ft, NULL, "id",
+ CTF_FIELD_TYPE_MEANING_EVENT_CLASS_ID);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ for (i = 0; i < sc->event_classes->len; i++) {
+ struct ctf_event_class *ec = sc->event_classes->pdata[i];
+
+ if (ec->is_translated) {
+ continue;
+ }
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_update_meanings(struct ctf_trace_class *ctf_tc)
+{
+ int ret = 0;
+ struct ctf_field_type_int *int_ft;
+ struct ctf_named_field_type *named_ft;
+ uint64_t i;
+
+ if (!ctf_tc->is_translated) {
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft, "magic");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_MAGIC;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft, "stream_id");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_STREAM_CLASS_ID;
+ }
+
+ int_ft = ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft,
+ "stream_instance_id");
+ if (int_ft) {
+ int_ft->meaning = CTF_FIELD_TYPE_MEANING_DATA_STREAM_ID;
+ }
+
+ named_ft = ctf_field_type_struct_borrow_member_by_name(
+ (void *) ctf_tc->packet_header_ft, "uuid");
+ if (named_ft && named_ft->ft->id == CTF_FIELD_TYPE_ID_ARRAY) {
+ struct ctf_field_type_array *array_ft =
+ (void *) named_ft->ft;
+
+ array_ft->meaning = CTF_FIELD_TYPE_MEANING_UUID;
+ }
+ }
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ ret = update_stream_class_meanings(
+ ctf_tc->stream_classes->pdata[i]);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-TEXT-ARRAY-SEQ"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static inline
+int set_text_array_sequence_field_type(struct ctf_field_type *ft)
+{
+ int ret = 0;
+ uint64_t i;
+
+ if (!ft) {
+ goto end;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ for (i = 0; i < struct_ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ ret = set_text_array_sequence_field_type(named_ft->ft);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ for (i = 0; i < var_ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ ret = set_text_array_sequence_field_type(named_ft->ft);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ if (array_ft->elem_ft->id == CTF_FIELD_TYPE_ID_INT ||
+ array_ft->elem_ft->id == CTF_FIELD_TYPE_ID_ENUM) {
+ struct ctf_field_type_int *int_ft =
+ (void *) array_ft->elem_ft;
+
+ if (int_ft->base.base.alignment == 8 &&
+ int_ft->base.size == 8 &&
+ int_ft->encoding == CTF_ENCODING_UTF8) {
+ array_ft->is_text = true;
+
+ /*
+ * Force integer element to be unsigned;
+ * this makes the decoder enter a single
+ * path when reading a text
+ * array/sequence and we can safely
+ * decode bytes as characters anyway.
+ */
+ int_ft->is_signed = false;
+ }
+ }
+
+ ret = set_text_array_sequence_field_type(array_ft->elem_ft);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_update_text_array_sequence(struct ctf_trace_class *ctf_tc)
+{
+ int ret = 0;
+ uint64_t i;
+
+ if (!ctf_tc->is_translated) {
+ ret = set_text_array_sequence_field_type(
+ ctf_tc->packet_header_ft);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
+ uint64_t j;
+
+ if (!sc->is_translated) {
+ ret = set_text_array_sequence_field_type(
+ sc->packet_context_ft);
+ if (ret) {
+ goto end;
+ }
+
+ ret = set_text_array_sequence_field_type(
+ sc->event_header_ft);
+ if (ret) {
+ goto end;
+ }
+
+ ret = set_text_array_sequence_field_type(
+ sc->event_common_context_ft);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ for (j = 0; j < sc->event_classes->len; j++) {
+ struct ctf_event_class *ec =
+ sc->event_classes->pdata[j];
+
+ if (ec->is_translated) {
+ continue;
+ }
+
+ ret = set_text_array_sequence_field_type(
+ ec->spec_context_ft);
+ if (ret) {
+ goto end;
+ }
+
+ ret = set_text_array_sequence_field_type(
+ ec->payload_ft);
+ if (ret) {
+ goto end;
+ }
+ }
+ }
+
+end:
+ return ret;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-UPDATE-VALUE-STORING-INDEXES"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static
+int update_field_type_stored_value_index(struct ctf_field_type *ft,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ int ret = 0;
+ uint64_t i;
+ struct ctf_field_path *field_path = NULL;
+ struct ctf_field_type_int *tgt_ft = NULL;
+ uint64_t *stored_value_index = NULL;
+
+ if (!ft) {
+ goto end;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ field_path = &var_ft->tag_path;
+ stored_value_index = &var_ft->stored_tag_index;
+ tgt_ft = (void *) var_ft->tag_ft;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_sequence *seq_ft = (void *) ft;
+
+ field_path = &seq_ft->length_path;
+ stored_value_index = &seq_ft->stored_length_index;
+ tgt_ft = seq_ft->length_ft;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (field_path) {
+ BT_ASSERT(tgt_ft);
+ BT_ASSERT(tgt_ft->base.base.id == CTF_FIELD_TYPE_ID_INT ||
+ tgt_ft->base.base.id == CTF_FIELD_TYPE_ID_ENUM);
+ if (tgt_ft->storing_index >= 0) {
+ /* Already storing its value */
+ *stored_value_index = (uint64_t) tgt_ft->storing_index;
+ } else {
+ /* Not storing its value: allocate new index */
+ tgt_ft->storing_index = tc->stored_value_count;
+ *stored_value_index = (uint64_t) tgt_ft->storing_index;
+ tc->stored_value_count++;
+ }
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ for (i = 0; i < struct_ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ ret = update_field_type_stored_value_index(named_ft->ft,
+ tc, sc, ec);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ for (i = 0; i < var_ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ ret = update_field_type_stored_value_index(named_ft->ft,
+ tc, sc, ec);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ ret = update_field_type_stored_value_index(array_ft->elem_ft,
+ tc, sc, ec);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_update_value_storing_indexes(struct ctf_trace_class *ctf_tc)
+{
+ uint64_t i;
+
+ if (!ctf_tc->is_translated) {
+ update_field_type_stored_value_index(
+ ctf_tc->packet_header_ft, ctf_tc, NULL, NULL);
+ }
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ uint64_t j;
+ struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
+
+ if (!sc->is_translated) {
+ update_field_type_stored_value_index(sc->packet_context_ft,
+ ctf_tc, sc, NULL);
+ update_field_type_stored_value_index(sc->event_header_ft,
+ ctf_tc, sc, NULL);
+ update_field_type_stored_value_index(
+ sc->event_common_context_ft, ctf_tc, sc, NULL);
+ }
+
+ for (j = 0; j < sc->event_classes->len; j++) {
+ struct ctf_event_class *ec =
+ sc->event_classes->pdata[j];
+
+ if (!ec->is_translated) {
+ update_field_type_stored_value_index(
+ ec->spec_context_ft, ctf_tc, sc, ec);
+ update_field_type_stored_value_index(
+ ec->payload_ft, ctf_tc, sc, ec);
+ }
+ }
+ }
+
+ return 0;
+}
--- /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.
+ */
+
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-VALIDATE"
+#include "logging.h"
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "ctf-meta-visitors.h"
+
+static
+int validate_stream_class(struct ctf_stream_class *sc)
+{
+ int ret = 0;
+ struct ctf_field_type_int *int_ft;
+ struct ctf_field_type *ft;
+ bool has_total_size = false;
+ bool has_content_size = false;
+
+ if (sc->is_translated) {
+ goto end;
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "timestamp_begin");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`timestamp_begin` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`timestamp_begin` member is signed.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "timestamp_end");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`timestamp_end` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`timestamp_end` member is signed.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "events_discarded");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`events_discarded` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`events_discarded` member is signed.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "packet_seq_num");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`packet_seq_num` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`packet_seq_num` member is signed.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "packet_size");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`packet_size` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`packet_size` member is signed.");
+ goto invalid;
+ }
+
+ has_total_size = true;
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->packet_context_ft, "content_size");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`content_size` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`content_size` member is signed.");
+ goto invalid;
+ }
+
+ has_content_size = true;
+ }
+
+ if (has_content_size && !has_total_size) {
+ BT_LOGE_STR("Invalid packet context field type: "
+ "`content_size` member exists without "
+ "`packet_size` member.");
+ goto invalid;
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) sc->event_header_ft, "id");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid event header field type: "
+ "`id` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid event header field type: "
+ "`id` member is signed.");
+ goto invalid;
+ }
+ } else {
+ if (sc->event_classes->len > 1) {
+ BT_LOGE_STR("Invalid event header field type: "
+ "missing `id` member as there's "
+ "more than one event class.");
+ goto invalid;
+ }
+ }
+
+ goto end;
+
+invalid:
+ ret = -1;
+
+end:
+ return ret;
+}
+
+BT_HIDDEN
+int ctf_trace_class_validate(struct ctf_trace_class *ctf_tc)
+{
+ int ret = 0;
+ struct ctf_field_type_int *int_ft;
+ uint64_t i;
+
+ if (!ctf_tc->is_translated) {
+ struct ctf_field_type *ft;
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft, "magic");
+ if (ft) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ (void *) ctf_tc->packet_header_ft,
+ 0);
+
+ if (named_ft->ft != ft) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`magic` member is not the first member.");
+ goto invalid;
+ }
+
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`magic` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`magic` member is signed.");
+ goto invalid;
+ }
+
+ if (int_ft->base.size != 32) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`magic` member is not 32-bit.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft, "stream_id");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`stream_id` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`stream_id` member is signed.");
+ goto invalid;
+ }
+ } else {
+ if (ctf_tc->stream_classes->len > 1) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "missing `stream_id` member as there's "
+ "more than one stream class.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft,
+ "stream_instance_id");
+ if (ft) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`stream_instance_id` member is not an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`stream_instance_id` member is signed.");
+ goto invalid;
+ }
+ }
+
+ ft = ctf_field_type_struct_borrow_member_field_type_by_name(
+ (void *) ctf_tc->packet_header_ft, "uuid");
+ if (ft) {
+ struct ctf_field_type_array *array_ft = (void *) ft;
+
+ if (ft->id != CTF_FIELD_TYPE_ID_ARRAY) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member is not an array field type.");
+ goto invalid;
+ }
+
+ array_ft = (void *) ft;
+
+ if (array_ft->length != 16) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member is not a 16-element array field type.");
+ goto invalid;
+ }
+
+ if (array_ft->base.elem_ft->id != CTF_FIELD_TYPE_ID_INT) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member's element field type is not "
+ "an integer field type.");
+ goto invalid;
+ }
+
+ int_ft = (void *) array_ft->base.elem_ft;
+
+ if (int_ft->is_signed) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member's element field type "
+ "is a signed integer field type.");
+ goto invalid;
+ }
+
+ if (int_ft->base.size != 8) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member's element field type "
+ "is not an 8-bit integer field type.");
+ goto invalid;
+ }
+
+ if (int_ft->base.base.alignment != 8) {
+ BT_LOGE_STR("Invalid packet header field type: "
+ "`uuid` member's element field type's "
+ "alignment is not 8.");
+ goto invalid;
+ }
+ }
+ }
+
+ for (i = 0; i < ctf_tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc =
+ ctf_tc->stream_classes->pdata[i];
+
+ ret = validate_stream_class(sc);
+ if (ret) {
+ BT_LOGE("Invalid stream class: sc-id=%" PRIu64, sc->id);
+ goto invalid;
+ }
+ }
+
+ goto end;
+
+invalid:
+ ret = -1;
+
+end:
+ return ret;
+}
--- /dev/null
+#ifndef _CTF_META_VISITORS_H
+#define _CTF_META_VISITORS_H
+
+/*
+ * Copyright 2018 - Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
+
+#include "ctf-meta.h"
+
+BT_HIDDEN
+int ctf_trace_class_resolve_field_types(struct ctf_trace_class *tc);
+
+BT_HIDDEN
+int ctf_trace_class_translate(struct bt_trace *ir_trace,
+ struct ctf_trace_class *tc);
+
+BT_HIDDEN
+int ctf_trace_class_update_default_clock_classes(
+ struct ctf_trace_class *ctf_tc);
+
+BT_HIDDEN
+int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc);
+
+BT_HIDDEN
+int ctf_trace_class_update_meanings(struct ctf_trace_class *ctf_tc);
+
+BT_HIDDEN
+int ctf_trace_class_update_text_array_sequence(struct ctf_trace_class *ctf_tc);
+
+BT_HIDDEN
+int ctf_trace_class_update_value_storing_indexes(struct ctf_trace_class *ctf_tc);
+
+BT_HIDDEN
+int ctf_trace_class_validate(struct ctf_trace_class *ctf_tc);
+
+#endif /* _CTF_META_VISITORS_H */
--- /dev/null
+#ifndef _CTF_META_H
+#define _CTF_META_H
+
+/*
+ * Copyright 2018 - Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <glib.h>
+#include <stdint.h>
+#include <string.h>
+
+enum ctf_field_type_id {
+ CTF_FIELD_TYPE_ID_INT,
+ CTF_FIELD_TYPE_ID_ENUM,
+ CTF_FIELD_TYPE_ID_FLOAT,
+ CTF_FIELD_TYPE_ID_STRING,
+ CTF_FIELD_TYPE_ID_STRUCT,
+ CTF_FIELD_TYPE_ID_ARRAY,
+ CTF_FIELD_TYPE_ID_SEQUENCE,
+ CTF_FIELD_TYPE_ID_VARIANT,
+};
+
+enum ctf_field_type_meaning {
+ CTF_FIELD_TYPE_MEANING_NONE,
+ CTF_FIELD_TYPE_MEANING_PACKET_BEGINNING_TIME,
+ CTF_FIELD_TYPE_MEANING_PACKET_END_TIME,
+ CTF_FIELD_TYPE_MEANING_EVENT_CLASS_ID,
+ CTF_FIELD_TYPE_MEANING_STREAM_CLASS_ID,
+ CTF_FIELD_TYPE_MEANING_DATA_STREAM_ID,
+ CTF_FIELD_TYPE_MEANING_MAGIC,
+ CTF_FIELD_TYPE_MEANING_PACKET_COUNTER_SNAPSHOT,
+ CTF_FIELD_TYPE_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT,
+ CTF_FIELD_TYPE_MEANING_EXP_PACKET_TOTAL_SIZE,
+ CTF_FIELD_TYPE_MEANING_EXP_PACKET_CONTENT_SIZE,
+ CTF_FIELD_TYPE_MEANING_UUID,
+};
+
+enum ctf_byte_order {
+ CTF_BYTE_ORDER_DEFAULT,
+ CTF_BYTE_ORDER_LITTLE,
+ CTF_BYTE_ORDER_BIG,
+};
+
+enum ctf_encoding {
+ CTF_ENCODING_NONE,
+ CTF_ENCODING_UTF8,
+};
+
+struct ctf_field_type {
+ enum ctf_field_type_id id;
+ unsigned int alignment;
+ bool is_compound;
+ bool in_ir;
+
+ /* Weak, set during translation. NULL if `in_ir` is false below. */
+ struct bt_field_type *ir_ft;
+};
+
+struct ctf_field_type_bit_array {
+ struct ctf_field_type base;
+ enum ctf_byte_order byte_order;
+ unsigned int size;
+};
+
+struct ctf_field_type_int {
+ struct ctf_field_type_bit_array base;
+ enum ctf_field_type_meaning meaning;
+ bool is_signed;
+ enum bt_field_type_integer_preferred_display_base disp_base;
+ enum ctf_encoding encoding;
+ int64_t storing_index;
+
+ /* Owned by this */
+ struct bt_clock_class *mapped_clock_class;
+};
+
+struct ctf_range {
+ union {
+ uint64_t u;
+ int64_t i;
+ } lower;
+
+ union {
+ uint64_t u;
+ int64_t i;
+ } upper;
+};
+
+struct ctf_field_type_enum_mapping {
+ GString *label;
+ struct ctf_range range;
+};
+
+struct ctf_field_type_enum {
+ struct ctf_field_type_int base;
+
+ /* Array of `struct ctf_field_type_enum_mapping` */
+ GArray *mappings;
+};
+
+struct ctf_field_type_float {
+ struct ctf_field_type_bit_array base;
+};
+
+struct ctf_field_type_string {
+ struct ctf_field_type base;
+ enum ctf_encoding encoding;
+};
+
+struct ctf_named_field_type {
+ GString *name;
+
+ /* Owned by this */
+ struct ctf_field_type *ft;
+};
+
+struct ctf_field_type_struct {
+ struct ctf_field_type base;
+
+ /* Array of `struct ctf_named_field_type` */
+ GArray *members;
+};
+
+struct ctf_field_path {
+ enum bt_scope root;
+
+ /* Array of `int64_t` */
+ GArray *path;
+};
+
+struct ctf_field_type_variant_range {
+ struct ctf_range range;
+ uint64_t option_index;
+};
+
+struct ctf_field_type_variant {
+ struct ctf_field_type base;
+ GString *tag_ref;
+ struct ctf_field_path tag_path;
+ uint64_t stored_tag_index;
+
+ /* Array of `struct ctf_named_field_type` */
+ GArray *options;
+
+ /* Array of `struct ctf_field_type_variant_range` */
+ GArray *ranges;
+
+ /* Weak */
+ struct ctf_field_type_enum *tag_ft;
+};
+
+struct ctf_field_type_array_base {
+ struct ctf_field_type base;
+ struct ctf_field_type *elem_ft;
+ bool is_text;
+};
+
+struct ctf_field_type_array {
+ struct ctf_field_type_array_base base;
+ enum ctf_field_type_meaning meaning;
+ uint64_t length;
+};
+
+struct ctf_field_type_sequence {
+ struct ctf_field_type_array_base base;
+ GString *length_ref;
+ struct ctf_field_path length_path;
+ uint64_t stored_length_index;
+
+ /* Weak */
+ struct ctf_field_type_int *length_ft;
+};
+
+struct ctf_event_class {
+ GString *name;
+ uint64_t id;
+ GString *emf_uri;
+ enum bt_event_class_log_level log_level;
+ bool is_translated;
+
+ /* Owned by this */
+ struct ctf_field_type *spec_context_ft;
+
+ /* Owned by this */
+ struct ctf_field_type *payload_ft;
+
+ /* Weak, set during translation */
+ struct bt_event_class *ir_ec;
+};
+
+struct ctf_stream_class {
+ uint64_t id;
+ bool is_translated;
+
+ /* Owned by this */
+ struct ctf_field_type *packet_context_ft;
+
+ /* Owned by this */
+ struct ctf_field_type *event_header_ft;
+
+ /* Owned by this */
+ struct ctf_field_type *event_common_context_ft;
+
+ /* Array of `struct ctf_event_class *`, owned by this */
+ GPtrArray *event_classes;
+
+ /*
+ * Hash table mapping event class IDs to `struct ctf_event_class *`,
+ * weak.
+ */
+ GHashTable *event_classes_by_id;
+
+ /* Owned by this */
+ struct bt_clock_class *default_clock_class;
+
+ /* Weak, set during translation */
+ struct bt_stream_class *ir_sc;
+};
+
+enum ctf_trace_class_env_entry_type {
+ CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
+ CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
+};
+
+struct ctf_trace_class_env_entry {
+ enum ctf_trace_class_env_entry_type type;
+ GString *name;
+
+ struct {
+ int64_t i;
+ GString *str;
+ } value;
+};
+
+struct ctf_trace_class {
+ GString *name;
+ unsigned int major;
+ unsigned int minor;
+ uint8_t uuid[16];
+ bool is_uuid_set;
+ enum ctf_byte_order default_byte_order;
+
+ /* Owned by this */
+ struct ctf_field_type *packet_header_ft;
+
+ uint64_t stored_value_count;
+
+ /* Array of `struct bt_clock_class *` (owned by this) */
+ GPtrArray *clock_classes;
+
+ /* Array of `struct ctf_stream_class *` */
+ GPtrArray *stream_classes;
+
+ /* Array of `struct ctf_trace_class_env_entry` */
+ GArray *env_entries;
+
+ bool is_translated;
+
+ /* Weak, set during translation */
+ struct bt_trace *ir_tc;
+};
+
+static inline
+void ctf_field_type_destroy(struct ctf_field_type *ft);
+
+static inline
+void _ctf_field_type_init(struct ctf_field_type *ft, enum ctf_field_type_id id,
+ unsigned int alignment)
+{
+ BT_ASSERT(ft);
+ ft->id = id;
+ ft->alignment = alignment;
+ ft->in_ir = false;
+}
+
+static inline
+void _ctf_field_type_bit_array_init(struct ctf_field_type_bit_array *ft,
+ enum ctf_field_type_id id)
+{
+ _ctf_field_type_init((void *) ft, id, 1);
+}
+
+static inline
+void _ctf_field_type_int_init(struct ctf_field_type_int *ft,
+ enum ctf_field_type_id id)
+{
+ _ctf_field_type_bit_array_init((void *) ft, id);
+ ft->meaning = CTF_FIELD_TYPE_MEANING_NONE;
+ ft->storing_index = -1;
+}
+
+static inline
+void ctf_field_path_init(struct ctf_field_path *field_path)
+{
+ BT_ASSERT(field_path);
+ field_path->path = g_array_new(FALSE, TRUE, sizeof(int64_t));
+ BT_ASSERT(field_path->path);
+}
+
+static inline
+void ctf_field_path_fini(struct ctf_field_path *field_path)
+{
+ BT_ASSERT(field_path);
+
+ if (field_path->path) {
+ g_array_free(field_path->path, TRUE);
+ }
+}
+
+static inline
+void _ctf_named_field_type_init(struct ctf_named_field_type *named_ft)
+{
+ BT_ASSERT(named_ft);
+ named_ft->name = g_string_new(NULL);
+ BT_ASSERT(named_ft->name);
+}
+
+static inline
+void _ctf_named_field_type_fini(struct ctf_named_field_type *named_ft)
+{
+ BT_ASSERT(named_ft);
+
+ if (named_ft->name) {
+ g_string_free(named_ft->name, TRUE);
+ }
+
+ ctf_field_type_destroy(named_ft->ft);
+}
+
+static inline
+void _ctf_field_type_enum_mapping_init(
+ struct ctf_field_type_enum_mapping *mapping)
+{
+ BT_ASSERT(mapping);
+ mapping->label = g_string_new(NULL);
+ BT_ASSERT(mapping->label);
+}
+
+static inline
+void _ctf_field_type_enum_mapping_fini(
+ struct ctf_field_type_enum_mapping *mapping)
+{
+ BT_ASSERT(mapping);
+
+ if (mapping->label) {
+ g_string_free(mapping->label, TRUE);
+ }
+}
+
+static inline
+struct ctf_field_type_int *ctf_field_type_int_create(void)
+{
+ struct ctf_field_type_int *ft = g_new0(struct ctf_field_type_int, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_int_init(ft, CTF_FIELD_TYPE_ID_INT);
+ return ft;
+}
+
+static inline
+struct ctf_field_type_float *ctf_field_type_float_create(void)
+{
+ struct ctf_field_type_float *ft =
+ g_new0(struct ctf_field_type_float, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_bit_array_init((void *) ft, CTF_FIELD_TYPE_ID_FLOAT);
+ return ft;
+}
+
+static inline
+struct ctf_field_type_string *ctf_field_type_string_create(void)
+{
+ struct ctf_field_type_string *ft =
+ g_new0(struct ctf_field_type_string, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_init((void *) ft, CTF_FIELD_TYPE_ID_STRING, 8);
+ return ft;
+}
+
+static inline
+struct ctf_field_type_enum *ctf_field_type_enum_create(void)
+{
+ struct ctf_field_type_enum *ft = g_new0(struct ctf_field_type_enum, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_int_init((void *) ft, CTF_FIELD_TYPE_ID_ENUM);
+ ft->mappings = g_array_new(FALSE, TRUE,
+ sizeof(struct ctf_field_type_enum_mapping));
+ BT_ASSERT(ft->mappings);
+ return ft;
+}
+
+static inline
+struct ctf_field_type_struct *ctf_field_type_struct_create(void)
+{
+ struct ctf_field_type_struct *ft =
+ g_new0(struct ctf_field_type_struct, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_init((void *) ft, CTF_FIELD_TYPE_ID_STRUCT, 1);
+ ft->members = g_array_new(FALSE, TRUE,
+ sizeof(struct ctf_named_field_type));
+ BT_ASSERT(ft->members);
+ ft->base.is_compound = true;
+ return ft;
+}
+
+static inline
+struct ctf_field_type_variant *ctf_field_type_variant_create(void)
+{
+ struct ctf_field_type_variant *ft =
+ g_new0(struct ctf_field_type_variant, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_init((void *) ft, CTF_FIELD_TYPE_ID_VARIANT, 1);
+ ft->options = g_array_new(FALSE, TRUE,
+ sizeof(struct ctf_named_field_type));
+ BT_ASSERT(ft->options);
+ ft->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct ctf_field_type_variant_range));
+ BT_ASSERT(ft->ranges);
+ ft->tag_ref = g_string_new(NULL);
+ BT_ASSERT(ft->tag_ref);
+ ctf_field_path_init(&ft->tag_path);
+ ft->base.is_compound = true;
+ return ft;
+}
+
+static inline
+struct ctf_field_type_array *ctf_field_type_array_create(void)
+{
+ struct ctf_field_type_array *ft =
+ g_new0(struct ctf_field_type_array, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_init((void *) ft, CTF_FIELD_TYPE_ID_ARRAY, 1);
+ ft->base.base.is_compound = true;
+ return ft;
+}
+
+static inline
+struct ctf_field_type_sequence *ctf_field_type_sequence_create(void)
+{
+ struct ctf_field_type_sequence *ft =
+ g_new0(struct ctf_field_type_sequence, 1);
+
+ BT_ASSERT(ft);
+ _ctf_field_type_init((void *) ft, CTF_FIELD_TYPE_ID_SEQUENCE, 1);
+ ft->length_ref = g_string_new(NULL);
+ BT_ASSERT(ft->length_ref);
+ ctf_field_path_init(&ft->length_path);
+ ft->base.base.is_compound = true;
+ return ft;
+}
+
+static inline
+void _ctf_field_type_int_destroy(struct ctf_field_type_int *ft)
+{
+ BT_ASSERT(ft);
+ bt_put(ft->mapped_clock_class);
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_enum_destroy(struct ctf_field_type_enum *ft)
+{
+ BT_ASSERT(ft);
+ bt_put(ft->base.mapped_clock_class);
+
+ if (ft->mappings) {
+ uint64_t i;
+
+ for (i = 0; i < ft->mappings->len; i++) {
+ struct ctf_field_type_enum_mapping *mapping =
+ &g_array_index(ft->mappings,
+ struct ctf_field_type_enum_mapping, i);
+
+ _ctf_field_type_enum_mapping_fini(mapping);
+ }
+
+ g_array_free(ft->mappings, TRUE);
+ }
+
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_float_destroy(struct ctf_field_type_float *ft)
+{
+ BT_ASSERT(ft);
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_string_destroy(struct ctf_field_type_string *ft)
+{
+ BT_ASSERT(ft);
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_struct_destroy(struct ctf_field_type_struct *ft)
+{
+ BT_ASSERT(ft);
+
+ if (ft->members) {
+ uint64_t i;
+
+ for (i = 0; i < ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ &g_array_index(ft->members,
+ struct ctf_named_field_type, i);
+
+ _ctf_named_field_type_fini(named_ft);
+ }
+
+ g_array_free(ft->members, TRUE);
+ }
+
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_array_base_fini(struct ctf_field_type_array_base *ft)
+{
+ BT_ASSERT(ft);
+ ctf_field_type_destroy(ft->elem_ft);
+}
+
+static inline
+void _ctf_field_type_array_destroy(struct ctf_field_type_array *ft)
+{
+ BT_ASSERT(ft);
+ _ctf_field_type_array_base_fini((void *) ft);
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_sequence_destroy(struct ctf_field_type_sequence *ft)
+{
+ BT_ASSERT(ft);
+ _ctf_field_type_array_base_fini((void *) ft);
+
+ if (ft->length_ref) {
+ g_string_free(ft->length_ref, TRUE);
+ }
+
+ ctf_field_path_fini(&ft->length_path);
+ g_free(ft);
+}
+
+static inline
+void _ctf_field_type_variant_destroy(struct ctf_field_type_variant *ft)
+{
+ BT_ASSERT(ft);
+
+ if (ft->options) {
+ uint64_t i;
+
+ for (i = 0; i < ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ &g_array_index(ft->options,
+ struct ctf_named_field_type, i);
+
+ _ctf_named_field_type_fini(named_ft);
+ }
+
+ g_array_free(ft->options, TRUE);
+ }
+
+ if (ft->ranges) {
+ g_array_free(ft->ranges, TRUE);
+ }
+
+ if (ft->tag_ref) {
+ g_string_free(ft->tag_ref, TRUE);
+ }
+
+ ctf_field_path_fini(&ft->tag_path);
+ g_free(ft);
+}
+
+static inline
+void ctf_field_type_destroy(struct ctf_field_type *ft)
+{
+ if (!ft) {
+ return;
+ }
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ _ctf_field_type_int_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_ENUM:
+ _ctf_field_type_enum_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_FLOAT:
+ _ctf_field_type_float_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRING:
+ _ctf_field_type_string_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ _ctf_field_type_struct_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ _ctf_field_type_array_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ _ctf_field_type_sequence_destroy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ _ctf_field_type_variant_destroy((void *) ft);
+ break;
+ default:
+ abort();
+ }
+}
+
+static inline
+void ctf_field_type_enum_append_mapping(struct ctf_field_type_enum *ft,
+ const char *label, uint64_t u_lower, uint64_t u_upper)
+{
+ struct ctf_field_type_enum_mapping *mapping;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(label);
+ g_array_set_size(ft->mappings, ft->mappings->len + 1);
+
+ mapping = &g_array_index(ft->mappings,
+ struct ctf_field_type_enum_mapping, ft->mappings->len - 1);
+ _ctf_field_type_enum_mapping_init(mapping);
+ g_string_assign(mapping->label, label);
+ mapping->range.lower.u = u_lower;
+ mapping->range.upper.u = u_upper;
+}
+
+static inline
+struct ctf_field_type_enum_mapping *ctf_field_type_enum_borrow_mapping_by_index(
+ struct ctf_field_type_enum *ft, uint64_t index)
+{
+ BT_ASSERT(ft);
+ BT_ASSERT(index < ft->mappings->len);
+ return &g_array_index(ft->mappings, struct ctf_field_type_enum_mapping,
+ index);
+}
+
+static inline
+struct ctf_named_field_type *ctf_field_type_struct_borrow_member_by_index(
+ struct ctf_field_type_struct *ft, uint64_t index)
+{
+ BT_ASSERT(ft);
+ BT_ASSERT(index < ft->members->len);
+ return &g_array_index(ft->members, struct ctf_named_field_type,
+ index);
+}
+
+static inline
+struct ctf_named_field_type *ctf_field_type_struct_borrow_member_by_name(
+ struct ctf_field_type_struct *ft, const char *name)
+{
+ uint64_t i;
+ struct ctf_named_field_type *ret_named_ft = NULL;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(name);
+
+ for (i = 0; i < ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(ft, i);
+
+ if (strcmp(name, named_ft->name->str) == 0) {
+ ret_named_ft = named_ft;
+ goto end;
+ }
+ }
+
+end:
+ return ret_named_ft;
+}
+
+static inline
+struct ctf_field_type *ctf_field_type_struct_borrow_member_field_type_by_name(
+ struct ctf_field_type_struct *struct_ft, const char *name)
+{
+ struct ctf_named_field_type *named_ft = NULL;
+ struct ctf_field_type *ft = NULL;
+
+ if (!struct_ft) {
+ goto end;
+ }
+
+ named_ft = ctf_field_type_struct_borrow_member_by_name(struct_ft, name);
+ if (!named_ft) {
+ goto end;
+ }
+
+ ft = named_ft->ft;
+
+end:
+ return ft;
+}
+
+static inline
+struct ctf_field_type_int *
+ctf_field_type_struct_borrow_member_int_field_type_by_name(
+ struct ctf_field_type_struct *struct_ft, const char *name)
+{
+ struct ctf_field_type_int *int_ft = NULL;
+
+ int_ft = (void *)
+ ctf_field_type_struct_borrow_member_field_type_by_name(
+ struct_ft, name);
+ if (!int_ft) {
+ goto end;
+ }
+
+ if (int_ft->base.base.id != CTF_FIELD_TYPE_ID_INT &&
+ int_ft->base.base.id != CTF_FIELD_TYPE_ID_ENUM) {
+ int_ft = NULL;
+ goto end;
+ }
+
+end:
+ return int_ft;
+}
+
+
+static inline
+void ctf_field_type_struct_append_member(struct ctf_field_type_struct *ft,
+ const char *name, struct ctf_field_type *member_ft)
+{
+ struct ctf_named_field_type *named_ft;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(name);
+ g_array_set_size(ft->members, ft->members->len + 1);
+
+ named_ft = &g_array_index(ft->members, struct ctf_named_field_type,
+ ft->members->len - 1);
+ _ctf_named_field_type_init(named_ft);
+ g_string_assign(named_ft->name, name);
+ named_ft->ft = member_ft;
+
+ if (member_ft->alignment > ft->base.alignment) {
+ ft->base.alignment = member_ft->alignment;
+ }
+}
+
+static inline
+struct ctf_named_field_type *ctf_field_type_variant_borrow_option_by_index(
+ struct ctf_field_type_variant *ft, uint64_t index)
+{
+ BT_ASSERT(ft);
+ BT_ASSERT(index < ft->options->len);
+ return &g_array_index(ft->options, struct ctf_named_field_type,
+ index);
+}
+
+static inline
+struct ctf_named_field_type *ctf_field_type_variant_borrow_option_by_name(
+ struct ctf_field_type_variant *ft, const char *name)
+{
+ uint64_t i;
+ struct ctf_named_field_type *ret_named_ft = NULL;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(name);
+
+ for (i = 0; i < ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(ft, i);
+
+ if (strcmp(name, named_ft->name->str) == 0) {
+ ret_named_ft = named_ft;
+ goto end;
+ }
+ }
+
+end:
+ return ret_named_ft;
+}
+
+static inline
+struct ctf_field_type_variant_range *
+ctf_field_type_variant_borrow_range_by_index(
+ struct ctf_field_type_variant *ft, uint64_t index)
+{
+ BT_ASSERT(ft);
+ BT_ASSERT(index < ft->ranges->len);
+ return &g_array_index(ft->ranges, struct ctf_field_type_variant_range,
+ index);
+}
+
+static inline
+void ctf_field_type_variant_append_option(struct ctf_field_type_variant *ft,
+ const char *name, struct ctf_field_type *option_ft)
+{
+ struct ctf_named_field_type *named_ft;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(name);
+ g_array_set_size(ft->options, ft->options->len + 1);
+
+ named_ft = &g_array_index(ft->options, struct ctf_named_field_type,
+ ft->options->len - 1);
+ _ctf_named_field_type_init(named_ft);
+ g_string_assign(named_ft->name, name);
+ named_ft->ft = option_ft;
+}
+
+static inline
+void ctf_field_type_variant_set_tag_field_type(
+ struct ctf_field_type_variant *ft,
+ struct ctf_field_type_enum *tag_ft)
+{
+ uint64_t option_i;
+
+ BT_ASSERT(ft);
+ BT_ASSERT(tag_ft);
+ ft->tag_ft = tag_ft;
+
+ for (option_i = 0; option_i < ft->options->len; option_i++) {
+ uint64_t mapping_i;
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ ft, option_i);
+
+ for (mapping_i = 0; mapping_i < tag_ft->mappings->len;
+ mapping_i++) {
+ struct ctf_field_type_enum_mapping *mapping =
+ ctf_field_type_enum_borrow_mapping_by_index(
+ tag_ft, mapping_i);
+
+ if (strcmp(named_ft->name->str,
+ mapping->label->str) == 0) {
+ struct ctf_field_type_variant_range range;
+
+ range.range = mapping->range;
+ range.option_index = option_i;
+ g_array_append_val(ft->ranges, range);
+ }
+ }
+ }
+}
+
+static inline
+struct ctf_field_type *ctf_field_type_compound_borrow_field_type_by_index(
+ struct ctf_field_type *comp_ft, uint64_t index)
+{
+ struct ctf_field_type *ft = NULL;
+
+ switch (comp_ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ (void *) comp_ft, index);
+
+ BT_ASSERT(named_ft);
+ ft = named_ft->ft;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ (void *) comp_ft, index);
+
+ BT_ASSERT(named_ft);
+ ft = named_ft->ft;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct ctf_field_type_array_base *array_ft = (void *) comp_ft;
+
+ ft = array_ft->elem_ft;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ft;
+}
+
+static inline
+uint64_t ctf_field_type_compound_get_field_type_count(struct ctf_field_type *ft)
+{
+ uint64_t field_count;
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ field_count = struct_ft->members->len;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ field_count = var_ft->options->len;
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ /*
+ * Array and sequence types always contain a single
+ * member (the element type).
+ */
+ field_count = 1;
+ break;
+ default:
+ abort();
+ }
+
+ return field_count;
+}
+
+static inline
+int64_t ctf_field_type_compound_get_field_type_index_from_name(
+ struct ctf_field_type *ft, const char *name)
+{
+ int64_t ret_index = -1;
+ uint64_t i;
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ {
+ struct ctf_field_type_struct *struct_ft = (void *) ft;
+
+ for (i = 0; i < struct_ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+
+ if (strcmp(name, named_ft->name->str) == 0) {
+ ret_index = (int64_t) i;
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ {
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+
+ for (i = 0; i < var_ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
+
+ if (strcmp(name, named_ft->name->str) == 0) {
+ ret_index = (int64_t) i;
+ goto end;
+ }
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret_index;
+}
+
+static inline
+void ctf_field_path_append_index(struct ctf_field_path *fp, int64_t index)
+{
+ BT_ASSERT(fp);
+ g_array_append_val(fp->path, index);
+}
+
+static inline
+int64_t ctf_field_path_borrow_index_by_index(struct ctf_field_path *fp,
+ uint64_t index)
+{
+ BT_ASSERT(fp);
+ BT_ASSERT(index < fp->path->len);
+ return g_array_index(fp->path, int64_t, index);
+}
+
+static inline
+void ctf_field_path_clear(struct ctf_field_path *fp)
+{
+ BT_ASSERT(fp);
+ g_array_set_size(fp->path, 0);
+}
+
+static inline
+GString *ctf_field_path_string(struct ctf_field_path *path)
+{
+ GString *str = g_string_new(NULL);
+ uint64_t i;
+
+ BT_ASSERT(path);
+
+ if (!str) {
+ goto end;
+ }
+
+ g_string_append_printf(str, "[%s", bt_common_scope_string(
+ path->root));
+
+ for (i = 0; i < path->path->len; i++) {
+ g_string_append_printf(str, ", %" PRId64,
+ ctf_field_path_borrow_index_by_index(path, i));
+ }
+
+ g_string_append(str, "]");
+
+end:
+ return str;
+}
+
+static inline
+struct ctf_field_type *ctf_field_path_borrow_field_type(
+ struct ctf_field_path *field_path,
+ struct ctf_trace_class *tc,
+ struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ uint64_t i;
+ struct ctf_field_type *ft;
+
+ switch (field_path->root) {
+ case BT_SCOPE_PACKET_HEADER:
+ ft = tc->packet_header_ft;
+ break;
+ case BT_SCOPE_PACKET_CONTEXT:
+ ft = sc->packet_context_ft;
+ break;
+ case BT_SCOPE_EVENT_HEADER:
+ ft = sc->event_header_ft;
+ break;
+ case BT_SCOPE_EVENT_COMMON_CONTEXT:
+ ft = sc->event_common_context_ft;
+ break;
+ case BT_SCOPE_EVENT_SPECIFIC_CONTEXT:
+ ft = ec->spec_context_ft;
+ break;
+ case BT_SCOPE_EVENT_PAYLOAD:
+ ft = ec->payload_ft;
+ break;
+ default:
+ abort();
+ }
+
+ BT_ASSERT(ft);
+
+ for (i = 0; i < field_path->path->len; i++) {
+ int64_t child_index =
+ ctf_field_path_borrow_index_by_index(field_path, i);
+ struct ctf_field_type *child_ft =
+ ctf_field_type_compound_borrow_field_type_by_index(
+ ft, child_index);
+ BT_ASSERT(child_ft);
+ ft = child_ft;
+ }
+
+ BT_ASSERT(ft);
+ return ft;
+}
+
+static inline
+struct ctf_field_type *ctf_field_type_copy(struct ctf_field_type *ft);
+
+static inline
+void ctf_field_type_bit_array_copy_content(
+ struct ctf_field_type_bit_array *dst_ft,
+ struct ctf_field_type_bit_array *src_ft)
+{
+ BT_ASSERT(dst_ft);
+ BT_ASSERT(src_ft);
+ dst_ft->byte_order = src_ft->byte_order;
+ dst_ft->size = src_ft->size;
+}
+
+static inline
+void ctf_field_type_int_copy_content(
+ struct ctf_field_type_int *dst_ft,
+ struct ctf_field_type_int *src_ft)
+{
+ ctf_field_type_bit_array_copy_content((void *) dst_ft, (void *) src_ft);
+ dst_ft->meaning = src_ft->meaning;
+ dst_ft->is_signed = src_ft->is_signed;
+ dst_ft->disp_base = src_ft->disp_base;
+ dst_ft->encoding = src_ft->encoding;
+ dst_ft->mapped_clock_class = bt_get(src_ft->mapped_clock_class);
+ dst_ft->storing_index = src_ft->storing_index;
+}
+
+static inline
+struct ctf_field_type_int *_ctf_field_type_int_copy(
+ struct ctf_field_type_int *ft)
+{
+ struct ctf_field_type_int *copy_ft = ctf_field_type_int_create();
+
+ BT_ASSERT(copy_ft);
+ ctf_field_type_int_copy_content(copy_ft, ft);
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type_enum *_ctf_field_type_enum_copy(
+ struct ctf_field_type_enum *ft)
+{
+ struct ctf_field_type_enum *copy_ft = ctf_field_type_enum_create();
+ uint64_t i;
+
+ BT_ASSERT(copy_ft);
+ ctf_field_type_int_copy_content((void *) copy_ft, (void *) ft);
+
+ for (i = 0; i < ft->mappings->len; i++) {
+ struct ctf_field_type_enum_mapping *mapping =
+ &g_array_index(ft->mappings,
+ struct ctf_field_type_enum_mapping, i);
+
+ ctf_field_type_enum_append_mapping(copy_ft, mapping->label->str,
+ mapping->range.lower.u, mapping->range.upper.u);
+ }
+
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type_float *_ctf_field_type_float_copy(
+ struct ctf_field_type_float *ft)
+{
+ struct ctf_field_type_float *copy_ft = ctf_field_type_float_create();
+
+ BT_ASSERT(copy_ft);
+ ctf_field_type_bit_array_copy_content((void *) copy_ft, (void *) ft);
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type_string *_ctf_field_type_string_copy(
+ struct ctf_field_type_string *ft)
+{
+ struct ctf_field_type_string *copy_ft = ctf_field_type_string_create();
+
+ BT_ASSERT(copy_ft);
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type_struct *_ctf_field_type_struct_copy(
+ struct ctf_field_type_struct *ft)
+{
+ struct ctf_field_type_struct *copy_ft = ctf_field_type_struct_create();
+ uint64_t i;
+
+ BT_ASSERT(copy_ft);
+
+ for (i = 0; i < ft->members->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ &g_array_index(ft->members,
+ struct ctf_named_field_type, i);
+
+ ctf_field_type_struct_append_member(copy_ft,
+ named_ft->name->str,
+ ctf_field_type_copy(named_ft->ft));
+ }
+
+ return copy_ft;
+}
+
+static inline
+void ctf_field_path_copy_content(struct ctf_field_path *dst_fp,
+ struct ctf_field_path *src_fp)
+{
+ uint64_t i;
+
+ BT_ASSERT(dst_fp);
+ BT_ASSERT(src_fp);
+ dst_fp->root = src_fp->root;
+ ctf_field_path_clear(dst_fp);
+
+ for (i = 0; i < src_fp->path->len; i++) {
+ int64_t index = ctf_field_path_borrow_index_by_index(
+ src_fp, i);
+
+ ctf_field_path_append_index(dst_fp, index);
+ }
+}
+
+static inline
+struct ctf_field_type_variant *_ctf_field_type_variant_copy(
+ struct ctf_field_type_variant *ft)
+{
+ struct ctf_field_type_variant *copy_ft =
+ ctf_field_type_variant_create();
+ uint64_t i;
+
+ BT_ASSERT(copy_ft);
+
+ for (i = 0; i < ft->options->len; i++) {
+ struct ctf_named_field_type *named_ft =
+ &g_array_index(ft->options,
+ struct ctf_named_field_type, i);
+
+ ctf_field_type_variant_append_option(copy_ft,
+ named_ft->name->str,
+ ctf_field_type_copy(named_ft->ft));
+ }
+
+ for (i = 0; i < ft->ranges->len; i++) {
+ struct ctf_field_type_variant_range *range =
+ &g_array_index(ft->ranges,
+ struct ctf_field_type_variant_range, i);
+
+ g_array_append_val(copy_ft->ranges, *range);
+ }
+
+ ctf_field_path_copy_content(©_ft->tag_path, &ft->tag_path);
+ g_string_assign(copy_ft->tag_ref, ft->tag_ref->str);
+ copy_ft->stored_tag_index = ft->stored_tag_index;
+ return copy_ft;
+}
+
+static inline
+void ctf_field_type_array_base_copy_content(
+ struct ctf_field_type_array_base *dst_ft,
+ struct ctf_field_type_array_base *src_ft)
+{
+ BT_ASSERT(dst_ft);
+ BT_ASSERT(src_ft);
+ dst_ft->elem_ft = ctf_field_type_copy(src_ft->elem_ft);
+ dst_ft->is_text = src_ft->is_text;
+}
+
+static inline
+struct ctf_field_type_array *_ctf_field_type_array_copy(
+ struct ctf_field_type_array *ft)
+{
+ struct ctf_field_type_array *copy_ft = ctf_field_type_array_create();
+
+ BT_ASSERT(copy_ft);
+ ctf_field_type_array_base_copy_content((void *) copy_ft, (void *) ft);
+ copy_ft->length = ft->length;
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type_sequence *_ctf_field_type_sequence_copy(
+ struct ctf_field_type_sequence *ft)
+{
+ struct ctf_field_type_sequence *copy_ft =
+ ctf_field_type_sequence_create();
+
+ BT_ASSERT(copy_ft);
+ ctf_field_type_array_base_copy_content((void *) copy_ft, (void *) ft);
+ ctf_field_path_copy_content(©_ft->length_path, &ft->length_path);
+ g_string_assign(copy_ft->length_ref, ft->length_ref->str);
+ copy_ft->stored_length_index = ft->stored_length_index;
+ return copy_ft;
+}
+
+static inline
+struct ctf_field_type *ctf_field_type_copy(struct ctf_field_type *ft)
+{
+ struct ctf_field_type *copy_ft = NULL;
+
+ if (!ft) {
+ goto end;
+ }
+
+ /*
+ * Translation should not have happened yet.
+ */
+ BT_ASSERT(!ft->ir_ft);
+
+ switch (ft->id) {
+ case CTF_FIELD_TYPE_ID_INT:
+ copy_ft = (void *) _ctf_field_type_int_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_ENUM:
+ copy_ft = (void *) _ctf_field_type_enum_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_FLOAT:
+ copy_ft = (void *) _ctf_field_type_float_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRING:
+ copy_ft = (void *) _ctf_field_type_string_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_STRUCT:
+ copy_ft = (void *) _ctf_field_type_struct_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_ARRAY:
+ copy_ft = (void *) _ctf_field_type_array_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_SEQUENCE:
+ copy_ft = (void *) _ctf_field_type_sequence_copy((void *) ft);
+ break;
+ case CTF_FIELD_TYPE_ID_VARIANT:
+ copy_ft = (void *) _ctf_field_type_variant_copy((void *) ft);
+ break;
+ default:
+ abort();
+ }
+
+ copy_ft->id = ft->id;
+ copy_ft->alignment = ft->alignment;
+ copy_ft->in_ir = ft->in_ir;
+
+end:
+ return copy_ft;
+}
+
+static inline
+struct ctf_event_class *ctf_event_class_create(void)
+{
+ struct ctf_event_class *ec = g_new0(struct ctf_event_class, 1);
+
+ BT_ASSERT(ec);
+ ec->name = g_string_new(NULL);
+ BT_ASSERT(ec->name);
+ ec->emf_uri = g_string_new(NULL);
+ BT_ASSERT(ec->emf_uri);
+ ec->log_level = -1;
+ return ec;
+}
+
+static inline
+void ctf_event_class_destroy(struct ctf_event_class *ec)
+{
+ if (!ec) {
+ return;
+ }
+
+ if (ec->name) {
+ g_string_free(ec->name, TRUE);
+ }
+
+ if (ec->emf_uri) {
+ g_string_free(ec->emf_uri, TRUE);
+ }
+
+ ctf_field_type_destroy(ec->spec_context_ft);
+ ctf_field_type_destroy(ec->payload_ft);
+ g_free(ec);
+}
+
+static inline
+struct ctf_stream_class *ctf_stream_class_create(void)
+{
+ struct ctf_stream_class *sc = g_new0(struct ctf_stream_class, 1);
+
+ BT_ASSERT(sc);
+ sc->event_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) ctf_event_class_destroy);
+ BT_ASSERT(sc->event_classes);
+ sc->event_classes_by_id = g_hash_table_new(g_direct_hash,
+ g_direct_equal);
+ BT_ASSERT(sc->event_classes_by_id);
+ return sc;
+}
+
+static inline
+void ctf_stream_class_destroy(struct ctf_stream_class *sc)
+{
+ if (!sc) {
+ return;
+ }
+
+ if (sc->event_classes) {
+ g_ptr_array_free(sc->event_classes, TRUE);
+ }
+
+ if (sc->event_classes_by_id) {
+ g_hash_table_destroy(sc->event_classes_by_id);
+ }
+
+ ctf_field_type_destroy(sc->packet_context_ft);
+ ctf_field_type_destroy(sc->event_header_ft);
+ ctf_field_type_destroy(sc->event_common_context_ft);
+ bt_put(sc->default_clock_class);
+ g_free(sc);
+}
+
+static inline
+void ctf_stream_class_append_event_class(struct ctf_stream_class *sc,
+ struct ctf_event_class *ec)
+{
+ g_ptr_array_add(sc->event_classes, ec);
+ g_hash_table_insert(sc->event_classes_by_id,
+ GUINT_TO_POINTER((guint) ec->id), ec);
+}
+
+static inline
+struct ctf_event_class *ctf_stream_class_borrow_event_class_by_id(
+ struct ctf_stream_class *sc, uint64_t id)
+{
+ BT_ASSERT(sc);
+ return g_hash_table_lookup(sc->event_classes_by_id,
+ GUINT_TO_POINTER((guint) id));
+}
+
+static inline
+void _ctf_trace_class_env_entry_init(struct ctf_trace_class_env_entry *entry)
+{
+ BT_ASSERT(entry);
+ entry->name = g_string_new(NULL);
+ BT_ASSERT(entry->name);
+ entry->value.str = g_string_new(NULL);
+ BT_ASSERT(entry->value.str);
+}
+
+static inline
+void _ctf_trace_class_env_entry_fini(struct ctf_trace_class_env_entry *entry)
+{
+ BT_ASSERT(entry);
+
+ if (entry->name) {
+ g_string_free(entry->name, TRUE);
+ }
+
+ if (entry->value.str) {
+ g_string_free(entry->value.str, TRUE);
+ }
+}
+
+static inline
+struct ctf_trace_class *ctf_trace_class_create(void)
+{
+ struct ctf_trace_class *tc = g_new0(struct ctf_trace_class, 1);
+
+ BT_ASSERT(tc);
+ tc->name = g_string_new(NULL);
+ tc->default_byte_order = -1;
+ BT_ASSERT(tc->name);
+ tc->clock_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) bt_put);
+ BT_ASSERT(tc->clock_classes);
+ tc->stream_classes = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) ctf_stream_class_destroy);
+ BT_ASSERT(tc->stream_classes);
+ tc->env_entries = g_array_new(FALSE, TRUE,
+ sizeof(struct ctf_trace_class_env_entry));
+ return tc;
+}
+
+static inline
+void ctf_trace_class_destroy(struct ctf_trace_class *tc)
+{
+ if (!tc) {
+ return;
+ }
+
+ if (tc->name) {
+ g_string_free(tc->name, TRUE);
+ }
+
+ ctf_field_type_destroy(tc->packet_header_ft);
+
+ if (tc->clock_classes) {
+ g_ptr_array_free(tc->clock_classes, TRUE);
+ }
+
+ if (tc->stream_classes) {
+ g_ptr_array_free(tc->stream_classes, TRUE);
+ }
+
+ if (tc->env_entries) {
+ uint64_t i;
+
+ for (i = 0; i < tc->env_entries->len; i++) {
+ struct ctf_trace_class_env_entry *entry =
+ &g_array_index(tc->env_entries,
+ struct ctf_trace_class_env_entry, i);
+
+ _ctf_trace_class_env_entry_fini(entry);
+ }
+
+ g_array_free(tc->env_entries, TRUE);
+ }
+
+ g_free(tc);
+}
+
+static inline
+void ctf_trace_class_append_env_entry(struct ctf_trace_class *tc,
+ const char *name, enum ctf_trace_class_env_entry_type type,
+ const char *str_value, int64_t i_value)
+{
+ struct ctf_trace_class_env_entry *entry;
+
+ BT_ASSERT(tc);
+ BT_ASSERT(name);
+ g_array_set_size(tc->env_entries, tc->env_entries->len + 1);
+
+ entry = &g_array_index(tc->env_entries,
+ struct ctf_trace_class_env_entry, tc->env_entries->len - 1);
+ entry->type = type;
+ _ctf_trace_class_env_entry_init(entry);
+ g_string_assign(entry->name, name);
+
+ if (str_value) {
+ g_string_assign(entry->value.str, str_value);
+ }
+
+ entry->value.i = i_value;
+}
+
+static inline
+struct ctf_stream_class *ctf_trace_class_borrow_stream_class_by_id(
+ struct ctf_trace_class *tc, uint64_t id)
+{
+ uint64_t i;
+ struct ctf_stream_class *ret_sc = NULL;
+
+ BT_ASSERT(tc);
+
+ for (i = 0; i < tc->stream_classes->len; i++) {
+ struct ctf_stream_class *sc = tc->stream_classes->pdata[i];
+
+ if (sc->id == id) {
+ ret_sc = sc;
+ goto end;
+ }
+ }
+
+end:
+ return ret_sc;
+}
+
+static inline
+struct bt_clock_class *ctf_trace_class_borrow_clock_class_by_name(
+ struct ctf_trace_class *tc, const char *name)
+{
+ uint64_t i;
+ struct bt_clock_class *ret_cc = NULL;
+
+ BT_ASSERT(tc);
+ BT_ASSERT(name);
+
+ for (i = 0; i < tc->clock_classes->len; i++) {
+ struct bt_clock_class *cc = tc->clock_classes->pdata[i];
+ const char *cc_name = bt_clock_class_get_name(cc);
+
+ BT_ASSERT(cc_name);
+ if (strcmp(cc_name, name) == 0) {
+ ret_cc = cc;
+ goto end;
+ }
+ }
+
+end:
+ return ret_cc;
+}
+
+static inline
+struct ctf_trace_class_env_entry *ctf_trace_class_borrow_env_entry_by_index(
+ struct ctf_trace_class *tc, uint64_t index)
+{
+ BT_ASSERT(tc);
+ BT_ASSERT(index < tc->env_entries->len);
+ return &g_array_index(tc->env_entries, struct ctf_trace_class_env_entry,
+ index);
+}
+
+static inline
+struct ctf_trace_class_env_entry *ctf_trace_class_borrow_env_entry_by_name(
+ struct ctf_trace_class *tc, const char *name)
+{
+ struct ctf_trace_class_env_entry *ret_entry = NULL;
+ uint64_t i;
+
+ BT_ASSERT(tc);
+ BT_ASSERT(name);
+
+ for (i = 0; i < tc->env_entries->len; i++) {
+ struct ctf_trace_class_env_entry *env_entry =
+ ctf_trace_class_borrow_env_entry_by_index(tc, i);
+
+ if (strcmp(env_entry->name->str, name) == 0) {
+ ret_entry = env_entry;
+ goto end;
+ }
+ }
+
+end:
+ return ret_entry;
+}
+
+#endif /* _CTF_META_H */
ret = ctf_visitor_generate_ir_visit_node(mdec->visitor,
&scanner->ast->root);
+ // TODO
+ ret = -1;
+ goto end;
+
switch (ret) {
case 0:
/* Success */
}
BT_HIDDEN
-struct bt_trace *ctf_metadata_decoder_get_trace(
+struct bt_trace *ctf_metadata_decoder_get_ir_trace(
+ struct ctf_metadata_decoder *mdec)
+{
+ return ctf_visitor_generate_ir_get_ir_trace(mdec->visitor);
+}
+
+BT_HIDDEN
+struct ctf_trace_class *ctf_metadata_decoder_borrow_ctf_trace_class(
struct ctf_metadata_decoder *mdec)
{
- return ctf_visitor_generate_ir_get_trace(mdec->visitor);
+ return ctf_visitor_generate_ir_borrow_ctf_trace_class(mdec->visitor);
}
* until the end of this file stream. If it finds new information (new
* event class, new stream class, or new clock class), it appends this
* information to the decoder's trace object (as returned by
- * ctf_metadata_get_trace()), or it creates this trace.
+ * ctf_metadata_decoder_get_ir_trace()), or it creates this trace.
*
* The metadata can be packetized or not.
*
enum ctf_metadata_decoder_status ctf_metadata_decoder_decode(
struct ctf_metadata_decoder *metadata_decoder, FILE *fp);
-/*
- * Returns a new reference to the current CTF IR trace object which is
- * the result of the metadata decoding process.
- *
- * The trace object, once created, remains the same until you call
- * ctf_metadata_decoder_destroy().
- */
BT_HIDDEN
-struct bt_trace *ctf_metadata_decoder_get_trace(
- struct ctf_metadata_decoder *metadata_decoder);
+struct bt_trace *ctf_metadata_decoder_get_ir_trace(
+ struct ctf_metadata_decoder *mdec);
+
+BT_HIDDEN
+struct ctf_trace_class *ctf_metadata_decoder_borrow_ctf_trace_class(
+ struct ctf_metadata_decoder *mdec);
/*
* Checks whether or not a given metadata file stream is packetized, and
* Based on older ctf-visitor-generate-io-struct.c.
*
* Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright 2015-2016 - Philippe Proulx <philippe.proulx@efficios.com>
+ * Copyright 2015-2018 - Philippe Proulx <philippe.proulx@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
#include "parser.h"
#include "ast.h"
#include "decoder.h"
+#include "ctf-meta.h"
+#include "ctf-meta-visitors.h"
/* Bit value (left shift) */
#define _BV(_val) (1 << (_val))
/* Set bit in a set of bits */
#define _SET(_set, _mask) (*(_set) |= (_mask))
+/* Try to push scope, or go to the `error` label */
+#define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
+ do { \
+ ret = ctx_push_scope(ctx); \
+ if (ret) { \
+ BT_LOGE_STR("Cannot push scope."); \
+ goto error; \
+ } \
+ } while (0)
+
/* Bits for verifying existing attributes in various declarations */
enum {
_CLOCK_NAME_SET = _BV(0),
_EVENT_ID_SET = _BV(1),
_EVENT_MODEL_EMF_URI_SET = _BV(2),
_EVENT_STREAM_ID_SET = _BV(3),
- _EVENT_LOGLEVEL_SET = _BV(4),
+ _EVENT_LOG_LEVEL_SET = _BV(4),
_EVENT_CONTEXT_SET = _BV(5),
_EVENT_FIELDS_SET = _BV(6),
};
enum loglevel {
- LOGLEVEL_EMERG = 0,
- LOGLEVEL_ALERT = 1,
- LOGLEVEL_CRIT = 2,
- LOGLEVEL_ERR = 3,
- LOGLEVEL_WARNING = 4,
- LOGLEVEL_NOTICE = 5,
- LOGLEVEL_INFO = 6,
- LOGLEVEL_DEBUG_SYSTEM = 7,
- LOGLEVEL_DEBUG_PROGRAM = 8,
- LOGLEVEL_DEBUG_PROCESS = 9,
- LOGLEVEL_DEBUG_MODULE = 10,
- LOGLEVEL_DEBUG_UNIT = 11,
- LOGLEVEL_DEBUG_FUNCTION = 12,
- LOGLEVEL_DEBUG_LINE = 13,
- LOGLEVEL_DEBUG = 14,
+ LOG_LEVEL_EMERG = 0,
+ LOG_LEVEL_ALERT = 1,
+ LOG_LEVEL_CRIT = 2,
+ LOG_LEVEL_ERR = 3,
+ LOG_LEVEL_WARNING = 4,
+ LOG_LEVEL_NOTICE = 5,
+ LOG_LEVEL_INFO = 6,
+ LOG_LEVEL_DEBUG_SYSTEM = 7,
+ LOG_LEVEL_DEBUG_PROGRAM = 8,
+ LOG_LEVEL_DEBUG_PROCESS = 9,
+ LOG_LEVEL_DEBUG_MODULE = 10,
+ LOG_LEVEL_DEBUG_UNIT = 11,
+ LOG_LEVEL_DEBUG_FUNCTION = 12,
+ LOG_LEVEL_DEBUG_LINE = 13,
+ LOG_LEVEL_DEBUG = 14,
_NR_LOGLEVELS = 15,
};
#define _PREFIX_VARIANT 'v'
/* First entry in a BT list */
-#define _BT_LIST_FIRST_ENTRY(_ptr, _type, _member) \
+#define _BT_LIST_FIRST_ENTRY(_ptr, _type, _member) \
bt_list_entry((_ptr)->next, _type, _member)
-#define _BT_FIELD_TYPE_INIT(_name) struct bt_field_type *_name = NULL;
-
#define _BT_LOGE_DUP_ATTR(_node, _attr, _entity) \
_BT_LOGE_LINENO((_node)->lineno, \
"Duplicate attribute in %s: attr-name=\"%s\"", \
/*
* Alias name to field type.
*
- * GQuark -> struct bt_field_type *
+ * GQuark -> struct ctf_field_type * (owned by this)
*/
GHashTable *decl_map;
* Visitor context (private).
*/
struct ctx {
- /* Trace being filled (owned by this) */
+ /* Trace IR trace being filled (owned by this) */
struct bt_trace *trace;
- /* Current declaration scope (top of the stack) */
+ /* CTF meta trace being filled (owned by this) */
+ struct ctf_trace_class *ctf_tc;
+
+ /* Current declaration scope (top of the stack) (owned by this) */
struct ctx_decl_scope *current_scope;
- /* 1 if trace declaration is visited */
- int is_trace_visited;
+ /* True if trace declaration is visited */
+ bool is_trace_visited;
- /* 1 if this is an LTTng trace */
+ /* True if this is an LTTng trace */
bool is_lttng;
- /* Eventual name suffix of the trace to set */
- char *trace_name_suffix;
-
- /* Trace attributes */
- enum bt_byte_order trace_bo;
- uint64_t trace_major;
- uint64_t trace_minor;
- unsigned char trace_uuid[BABELTRACE_UUID_LEN];
-
- /*
- * Stream IDs to stream classes.
- *
- * int64_t -> struct bt_stream_class *
- */
- GHashTable *stream_classes;
+ /* Eventual name suffix of the trace to set (owned by this) */
+ char *trace_class_name_suffix;
/* Config passed by the user */
struct ctf_metadata_decoder_config decoder_config;
/*
* Visitor (public).
*/
-struct ctf_visitor_generate_ir { };
+struct ctf_visitor_generate_ir;
/**
* Creates a new declaration scope.
}
scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) bt_put);
+ NULL, (GDestroyNotify) ctf_field_type_destroy);
scope->parent_scope = par_scope;
end:
* @param scope Declaration scope
* @param prefix Prefix character
* @param name Alias name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_field_type *ctx_decl_scope_lookup_prefix_alias(
- struct ctx_decl_scope *scope, char prefix,
- const char *name, int levels)
+struct ctf_field_type *ctx_decl_scope_lookup_prefix_alias(
+ struct ctx_decl_scope *scope, char prefix, const char *name,
+ int levels, bool copy)
{
GQuark qname = 0;
int cur_levels = 0;
- _BT_FIELD_TYPE_INIT(decl);
+ struct ctf_field_type *decl = NULL;
struct ctx_decl_scope *cur_scope = scope;
BT_ASSERT(scope);
BT_ASSERT(name);
qname = get_prefixed_named_quark(prefix, name);
if (!qname) {
- goto error;
+ goto end;
}
if (levels < 0) {
(gconstpointer) GUINT_TO_POINTER(qname));
if (decl) {
/* Caller's reference */
- bt_get(decl);
- break;
+ if (copy) {
+ decl = ctf_field_type_copy(decl);
+ BT_ASSERT(decl);
+ }
+
+ goto end;
}
cur_scope = cur_scope->parent_scope;
cur_levels++;
}
+end:
return decl;
-
-error:
- return NULL;
}
/**
*
* @param scope Declaration scope
* @param name Alias name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_field_type *ctx_decl_scope_lookup_alias(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_type *ctx_decl_scope_lookup_alias(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ALIAS,
- name, levels);
+ name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Enumeration name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_field_type *ctx_decl_scope_lookup_enum(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_type_enum *ctx_decl_scope_lookup_enum(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM,
+ name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Structure name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_field_type *ctx_decl_scope_lookup_struct(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_type_struct *ctx_decl_scope_lookup_struct(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_STRUCT,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope,
+ _PREFIX_STRUCT, name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Variant name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_field_type *ctx_decl_scope_lookup_variant(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_type_variant *ctx_decl_scope_lookup_variant(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_VARIANT,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope,
+ _PREFIX_VARIANT, name, levels, copy);
}
/**
* @param scope Declaration scope
* @param prefix Prefix character
* @param name Alias name (non-NULL)
- * @param decl Declaration to register
+ * @param decl Field type to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope *scope,
- char prefix, const char *name, struct bt_field_type *decl)
+ char prefix, const char *name, struct ctf_field_type *decl)
{
int ret = 0;
GQuark qname = 0;
- _BT_FIELD_TYPE_INIT(edecl);
BT_ASSERT(scope);
BT_ASSERT(name);
qname = get_prefixed_named_quark(prefix, name);
if (!qname) {
ret = -ENOMEM;
- goto error;
+ goto end;
}
/* Make sure alias does not exist in local scope */
- edecl = ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1);
- if (edecl) {
- BT_PUT(edecl);
+ if (ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1,
+ false)) {
ret = -EEXIST;
- goto error;
+ goto end;
}
- g_hash_table_insert(scope->decl_map,
- GUINT_TO_POINTER(qname), decl);
-
- /* Hash table's reference */
- bt_get(decl);
-
- return 0;
+ decl = ctf_field_type_copy(decl);
+ BT_ASSERT(decl);
+ g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl);
-error:
+end:
return ret;
}
*
* @param scope Declaration scope
* @param name Alias name (non-NULL)
- * @param decl Declaration to register
+ * @param decl Field type to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope,
- const char *name, struct bt_field_type *decl)
+ const char *name, struct ctf_field_type *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ALIAS,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Enumeration name (non-NULL)
- * @param decl Enumeration declaration to register
+ * @param decl Enumeration field type to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_enum(struct ctx_decl_scope *scope,
- const char *name, struct bt_field_type *decl)
+ const char *name, struct ctf_field_type_enum *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ENUM,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Structure name (non-NULL)
- * @param decl Structure declaration to register
+ * @param decl Structure field type to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_struct(struct ctx_decl_scope *scope,
- const char *name, struct bt_field_type *decl)
+ const char *name, struct ctf_field_type_struct *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_STRUCT,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Variant name (non-NULL)
- * @param decl Variant declaration to register
+ * @param decl Variant field type to register
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
- const char *name, struct bt_field_type *decl)
+ const char *name, struct ctf_field_type_variant *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_VARIANT,
- name, decl);
+ name, (void *) decl);
}
/**
void ctx_destroy(struct ctx *ctx)
{
struct ctx_decl_scope *scope;
- /*
- * Destroy all scopes, from current one to the root scope.
- */
if (!ctx) {
goto end;
scope = ctx->current_scope;
+ /*
+ * Destroy all scopes, from current one to the root scope.
+ */
while (scope) {
struct ctx_decl_scope *parent_scope = scope->parent_scope;
bt_put(ctx->trace);
- if (ctx->stream_classes) {
- g_hash_table_destroy(ctx->stream_classes);
+ if (ctx->ctf_tc) {
+ ctf_trace_class_destroy(ctx->ctf_tc);
+ }
+
+ if (ctx->trace_class_name_suffix) {
+ free(ctx->trace_class_name_suffix);
}
- free(ctx->trace_name_suffix);
g_free(ctx);
end:
* @returns New visitor context, or NULL on error
*/
static
-struct ctx *ctx_create(struct bt_trace *trace,
- const struct ctf_metadata_decoder_config *decoder_config,
- const char *trace_name_suffix)
+struct ctx *ctx_create(const struct ctf_metadata_decoder_config *decoder_config,
+ const char *trace_class_name_suffix)
{
struct ctx *ctx = NULL;
- struct ctx_decl_scope *scope = NULL;
BT_ASSERT(decoder_config);
goto error;
}
- /* Root declaration scope */
- scope = ctx_decl_scope_create(NULL);
- if (!scope) {
- BT_LOGE_STR("Cannot create declaration scope.");
+ ctx->trace = bt_trace_create();
+ if (!ctx->trace) {
+ BT_LOGE_STR("Cannot create empty trace.");
+ goto error;
+ }
+
+ ctx->ctf_tc = ctf_trace_class_create();
+ if (!ctx->ctf_tc) {
+ BT_LOGE_STR("Cannot create CTF trace class.");
goto error;
}
- ctx->stream_classes = g_hash_table_new_full(g_int64_hash,
- g_int64_equal, g_free, (GDestroyNotify) bt_put);
- if (!ctx->stream_classes) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
+ /* Root declaration scope */
+ ctx->current_scope = ctx_decl_scope_create(NULL);
+ if (!ctx->current_scope) {
+ BT_LOGE_STR("Cannot create declaration scope.");
goto error;
}
- if (trace_name_suffix) {
- ctx->trace_name_suffix = strdup(trace_name_suffix);
- if (!ctx->trace_name_suffix) {
+ if (trace_class_name_suffix) {
+ ctx->trace_class_name_suffix = strdup(trace_class_name_suffix);
+ if (!ctx->trace_class_name_suffix) {
BT_LOGE_STR("Failed to copy string.");
goto error;
}
}
- ctx->trace = trace;
- ctx->current_scope = scope;
- scope = NULL;
- ctx->trace_bo = BT_BYTE_ORDER_NATIVE;
ctx->decoder_config = *decoder_config;
- return ctx;
+ goto end;
error:
ctx_destroy(ctx);
- ctx_decl_scope_destroy(scope);
- return NULL;
+ ctx = NULL;
+
+end:
+ return ctx;
}
/**
static
int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list,
- struct bt_field_type **decl);
+ struct ctf_field_type **decl);
static
char *remove_underscores_from_field_ref(const char *field_ref)
}
static
-enum bt_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr)
+enum ctf_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr)
{
const char *str;
- enum bt_byte_order bo = BT_BYTE_ORDER_UNKNOWN;
+ enum ctf_byte_order bo = -1;
if (unary_expr->u.unary_expression.type != UNARY_STRING) {
_BT_LOGE_NODE(unary_expr,
str = unary_expr->u.unary_expression.u.string;
if (!strcmp(str, "be") || !strcmp(str, "network")) {
- bo = BT_BYTE_ORDER_BIG_ENDIAN;
+ bo = CTF_BYTE_ORDER_BIG;
} else if (!strcmp(str, "le")) {
- bo = BT_BYTE_ORDER_LITTLE_ENDIAN;
+ bo = CTF_BYTE_ORDER_LITTLE;
} else if (!strcmp(str, "native")) {
- bo = BT_BYTE_ORDER_NATIVE;
+ bo = CTF_BYTE_ORDER_DEFAULT;
} else {
_BT_LOGE_NODE(unary_expr,
"Unexpected \"byte_order\" attribute value: "
}
static
-enum bt_byte_order get_real_byte_order(struct ctx *ctx,
- struct ctf_node *uexpr)
+enum ctf_byte_order get_real_byte_order(struct ctx *ctx,
+ struct ctf_node *uexpr)
{
- enum bt_byte_order bo = byte_order_from_unary_expr(uexpr);
+ enum ctf_byte_order bo = byte_order_from_unary_expr(uexpr);
- if (bo == BT_BYTE_ORDER_NATIVE) {
- bo = bt_trace_get_native_byte_order(ctx->trace);
+ if (bo == CTF_BYTE_ORDER_DEFAULT) {
+ bo = ctx->ctf_tc->default_byte_order;
}
return bo;
static
int is_align_valid(uint64_t align)
{
- return (align != 0) && !(align & (align - 1ULL));
+ return (align != 0) && !(align & (align - UINT64_C(1)));
}
static
int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier,
- GString *str)
+ GString *str)
{
int ret = 0;
static
int get_type_specifier_list_name(struct ctx *ctx,
- struct ctf_node *type_specifier_list, GString *str)
+ struct ctf_node *type_specifier_list, GString *str)
{
int ret = 0;
struct ctf_node *iter;
static
GQuark create_typealias_identifier(struct ctx *ctx,
- struct ctf_node *type_specifier_list,
- struct ctf_node *node_type_declarator)
+ struct ctf_node *type_specifier_list,
+ struct ctf_node *node_type_declarator)
{
int ret;
char *str_c;
static
int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
- GQuark *field_name, struct ctf_node *node_type_declarator,
- struct bt_field_type **field_decl,
- struct bt_field_type *nested_decl)
+ GQuark *field_name, struct ctf_node *node_type_declarator,
+ struct ctf_field_type **field_decl,
+ struct ctf_field_type *nested_decl)
{
/*
* During this whole function, nested_decl is always OURS,
* whereas field_decl is an output which we create, but
* belongs to the caller (it is moved).
*/
-
int ret = 0;
*field_decl = NULL;
if (node_type_declarator && !bt_list_empty(pointers)) {
GQuark qalias;
- _BT_FIELD_TYPE_INIT(nested_decl_copy);
/*
* If we have a pointer declarator, it HAS to
- * be present in the typealiases (else fail).
+ * be present in the typealiases (else fail).
*/
qalias = create_typealias_identifier(ctx,
type_specifier_list, node_type_declarator);
nested_decl =
ctx_decl_scope_lookup_alias(ctx->current_scope,
- g_quark_to_string(qalias), -1);
+ g_quark_to_string(qalias), -1, true);
if (!nested_decl) {
_BT_LOGE_NODE(node_type_declarator,
"Cannot find type alias: name=\"%s\"",
goto error;
}
- /* Make a copy of it */
- nested_decl_copy = bt_field_type_copy(nested_decl);
- BT_PUT(nested_decl);
- if (!nested_decl_copy) {
- _BT_LOGE_NODE(node_type_declarator,
- "Cannot copy nested field type.");
- ret = -EINVAL;
- goto error;
- }
-
- BT_MOVE(nested_decl, nested_decl_copy);
+ if (nested_decl->id == CTF_FIELD_TYPE_ID_INT) {
+ /* Pointer: force integer's base to 16 */
+ struct ctf_field_type_int *int_ft =
+ (void *) nested_decl;
- /* Force integer's base to 16 since it's a pointer */
- if (bt_field_type_is_integer(nested_decl)) {
- ret = bt_field_type_integer_set_base(
- nested_decl,
- BT_INTEGER_BASE_HEXADECIMAL);
- BT_ASSERT(ret == 0);
+ int_ft->disp_base =
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
}
} else {
ret = visit_type_specifier_list(ctx,
BT_ASSERT(nested_decl);
if (!node_type_declarator) {
- BT_MOVE(*field_decl, nested_decl);
+ *field_decl = nested_decl;
+ nested_decl = NULL;
goto end;
}
*field_name = 0;
}
- BT_MOVE(*field_decl, nested_decl);
+ *field_decl = nested_decl;
+ nested_decl = NULL;
goto end;
} else {
struct ctf_node *first;
- _BT_FIELD_TYPE_INIT(decl);
- _BT_FIELD_TYPE_INIT(outer_field_decl);
+ struct ctf_field_type *decl = NULL;
+ struct ctf_field_type *outer_field_decl = NULL;
struct bt_list_head *length =
&node_type_declarator->
u.type_declarator.u.nested.length;
switch (first->u.unary_expression.type) {
case UNARY_UNSIGNED_CONSTANT:
{
- size_t len;
- _BT_FIELD_TYPE_INIT(array_decl);
-
- len = first->u.unary_expression.u.unsigned_constant;
- array_decl = bt_field_type_array_create(nested_decl,
- len);
- BT_PUT(nested_decl);
- if (!array_decl) {
- _BT_LOGE_NODE(first,
- "Cannot create array field type.");
- ret = -ENOMEM;
- goto error;
- }
-
- BT_MOVE(decl, array_decl);
+ struct ctf_field_type_array *array_decl = NULL;
+
+ array_decl = ctf_field_type_array_create();
+ BT_ASSERT(array_decl);
+ array_decl->length =
+ first->u.unary_expression.u.unsigned_constant;
+ array_decl->base.elem_ft = nested_decl;
+ nested_decl = NULL;
+ decl = (void *) array_decl;
break;
}
case UNARY_STRING:
{
/* Lookup unsigned integer definition, create seq. */
- _BT_FIELD_TYPE_INIT(seq_decl);
+ struct ctf_field_type_sequence *seq_decl = NULL;
char *length_name = concatenate_unary_strings(length);
- char *length_name_no_underscore;
if (!length_name) {
_BT_LOGE_NODE(node_type_declarator,
goto error;
}
- length_name_no_underscore =
- remove_underscores_from_field_ref(length_name);
- if (!length_name_no_underscore) {
- /* remove_underscores_from_field_ref() logs errors */
- ret = -EINVAL;
- goto error;
- }
- seq_decl = bt_field_type_sequence_create(
- nested_decl, length_name_no_underscore);
- free(length_name_no_underscore);
- g_free(length_name);
- BT_PUT(nested_decl);
- if (!seq_decl) {
- _BT_LOGE_NODE(node_type_declarator,
- "Cannot create sequence field type.");
- ret = -ENOMEM;
- goto error;
+ if (strncmp(length_name, "env.", 4) == 0) {
+ /* This is, in fact, an array */
+ const char *env_entry_name = &length_name[4];
+ struct ctf_trace_class_env_entry *env_entry =
+ ctf_trace_class_borrow_env_entry_by_name(
+ ctx->ctf_tc, env_entry_name);
+ struct ctf_field_type_array *array_decl;
+
+ if (!env_entry) {
+ _BT_LOGE_NODE(node_type_declarator,
+ "Cannot find environment entry: "
+ "name=\"%s\"", env_entry_name);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
+ _BT_LOGE_NODE(node_type_declarator,
+ "Wrong environment entry type "
+ "(expecting integer): "
+ "name=\"%s\"", env_entry_name);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (env_entry->value.i < 0) {
+ _BT_LOGE_NODE(node_type_declarator,
+ "Invalid, negative array length: "
+ "env-entry-name=\"%s\", "
+ "value=%" PRId64,
+ env_entry_name,
+ env_entry->value.i);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ array_decl = ctf_field_type_array_create();
+ BT_ASSERT(array_decl);
+ array_decl->length =
+ (uint64_t) env_entry->value.i;
+ array_decl->base.elem_ft = nested_decl;
+ nested_decl = NULL;
+ decl = (void *) array_decl;
+ } else {
+ char *length_name_no_underscore =
+ remove_underscores_from_field_ref(
+ length_name);
+ if (!length_name_no_underscore) {
+ /*
+ * remove_underscores_from_field_ref()
+ * logs errors
+ */
+ ret = -EINVAL;
+ goto error;
+ }
+ seq_decl = ctf_field_type_sequence_create();
+ BT_ASSERT(seq_decl);
+ seq_decl->base.elem_ft = nested_decl;
+ nested_decl = NULL;
+ g_string_assign(seq_decl->length_ref,
+ length_name_no_underscore);
+ free(length_name_no_underscore);
+ decl = (void *) seq_decl;
}
- BT_MOVE(decl, seq_decl);
+ g_free(length_name);
break;
}
default:
}
BT_ASSERT(outer_field_decl);
- BT_MOVE(*field_decl, outer_field_decl);
+ *field_decl = outer_field_decl;
+ outer_field_decl = NULL;
}
-end:
- BT_PUT(nested_decl);
BT_ASSERT(*field_decl);
-
- return 0;
+ goto end;
error:
- BT_PUT(nested_decl);
- BT_PUT(*field_decl);
+ ctf_field_type_destroy(*field_decl);
+ *field_decl = NULL;
+ if (ret >= 0) {
+ ret = -1;
+ }
+
+end:
+ ctf_field_type_destroy(nested_decl);
+ nested_decl = NULL;
return ret;
}
static
int visit_struct_decl_field(struct ctx *ctx,
- struct bt_field_type *struct_decl,
- struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+ struct ctf_field_type_struct *struct_decl,
+ struct ctf_node *type_specifier_list,
+ struct bt_list_head *type_declarators)
{
int ret = 0;
struct ctf_node *iter;
- _BT_FIELD_TYPE_INIT(field_decl);
+ struct ctf_field_type *field_decl = NULL;
bt_list_for_each_entry(iter, type_declarators, siblings) {
field_decl = NULL;
GQuark qfield_name;
const char *field_name;
- _BT_FIELD_TYPE_INIT(efield_decl);
ret = visit_type_declarator(ctx, type_specifier_list,
&qfield_name, iter, &field_decl, NULL);
field_name = g_quark_to_string(qfield_name);
/* Check if field with same name already exists */
- efield_decl =
- bt_field_type_structure_get_field_type_by_name(
- struct_decl, field_name);
- if (efield_decl) {
- BT_PUT(efield_decl);
+ if (ctf_field_type_struct_borrow_member_by_name(
+ struct_decl, field_name)) {
_BT_LOGE_NODE(type_specifier_list,
"Duplicate field in structure field type: "
"field-name=\"%s\"", field_name);
}
/* Add field to structure */
- ret = bt_field_type_structure_add_field(struct_decl,
- field_decl, field_name);
- BT_PUT(field_decl);
- if (ret) {
- _BT_LOGE_NODE(type_specifier_list,
- "Cannot add field to structure field type: "
- "field-name=\"%s\", ret=%d",
- g_quark_to_string(qfield_name), ret);
- goto error;
- }
+ ctf_field_type_struct_append_member(struct_decl,
+ field_name, field_decl);
+ field_decl = NULL;
}
return 0;
error:
- BT_PUT(field_decl);
-
+ ctf_field_type_destroy(field_decl);
+ field_decl = NULL;
return ret;
}
static
int visit_variant_decl_field(struct ctx *ctx,
- struct bt_field_type *variant_decl,
- struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+ struct ctf_field_type_variant *variant_decl,
+ struct ctf_node *type_specifier_list,
+ struct bt_list_head *type_declarators)
{
int ret = 0;
struct ctf_node *iter;
- _BT_FIELD_TYPE_INIT(field_decl);
+ struct ctf_field_type *field_decl = NULL;
bt_list_for_each_entry(iter, type_declarators, siblings) {
field_decl = NULL;
GQuark qfield_name;
const char *field_name;
- _BT_FIELD_TYPE_INIT(efield_decl);
ret = visit_type_declarator(ctx, type_specifier_list,
&qfield_name, iter, &field_decl, NULL);
field_name = g_quark_to_string(qfield_name);
/* Check if field with same name already exists */
- efield_decl =
- bt_field_type_variant_get_field_type_by_name(
- variant_decl, field_name);
- if (efield_decl) {
- BT_PUT(efield_decl);
+ if (ctf_field_type_variant_borrow_option_by_name(
+ variant_decl, field_name)) {
_BT_LOGE_NODE(type_specifier_list,
"Duplicate field in variant field type: "
"field-name=\"%s\"", field_name);
}
/* Add field to structure */
- ret = bt_field_type_variant_add_field(variant_decl,
- field_decl, field_name);
- BT_PUT(field_decl);
- if (ret) {
- _BT_LOGE_NODE(type_specifier_list,
- "Cannot add field to variant field type: "
- "field-name=\"%s\", ret=%d",
- g_quark_to_string(qfield_name), ret);
- goto error;
- }
+ ctf_field_type_variant_append_option(variant_decl,
+ field_name, field_decl);
+ field_decl = NULL;
}
return 0;
error:
- BT_PUT(field_decl);
-
+ ctf_field_type_destroy(field_decl);
+ field_decl = NULL;
return ret;
}
static
int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+ struct bt_list_head *type_declarators)
{
int ret = 0;
GQuark qidentifier;
struct ctf_node *iter;
- _BT_FIELD_TYPE_INIT(type_decl);
+ struct ctf_field_type *type_decl = NULL;
bt_list_for_each_entry(iter, type_declarators, siblings) {
ret = visit_type_declarator(ctx, type_specifier_list,
}
/* Do not allow typedef and typealias of untagged variants */
- if (bt_field_type_is_variant(type_decl)) {
- if (bt_field_type_variant_get_tag_name(type_decl)) {
+ if (type_decl->id == CTF_FIELD_TYPE_ID_VARIANT) {
+ struct ctf_field_type_variant *var_ft =
+ (void *) type_decl;
+
+ if (var_ft->tag_path.path->len == 0) {
_BT_LOGE_NODE(iter,
"Type definition of untagged variant field type is not allowed.");
ret = -EPERM;
}
end:
- BT_PUT(type_decl);
-
+ ctf_field_type_destroy(type_decl);
+ type_decl = NULL;
return ret;
}
static
int visit_typealias(struct ctx *ctx, struct ctf_node *target,
- struct ctf_node *alias)
+ struct ctf_node *alias)
{
int ret = 0;
GQuark qalias;
struct ctf_node *node;
GQuark qdummy_field_name;
- _BT_FIELD_TYPE_INIT(type_decl);
+ struct ctf_field_type *type_decl = NULL;
/* Create target type declaration */
if (bt_list_empty(&target->u.typealias_target.type_declarators)) {
}
/* Do not allow typedef and typealias of untagged variants */
- if (bt_field_type_is_variant(type_decl)) {
- if (bt_field_type_variant_get_tag_name(type_decl)) {
+ if (type_decl->id == CTF_FIELD_TYPE_ID_VARIANT) {
+ struct ctf_field_type_variant *var_ft = (void *) type_decl;
+
+ if (var_ft->tag_path.path->len == 0) {
_BT_LOGE_NODE(target,
"Type definition of untagged variant field type is not allowed.");
ret = -EPERM;
}
end:
- BT_PUT(type_decl);
-
+ ctf_field_type_destroy(type_decl);
+ type_decl = NULL;
return ret;
}
static
int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_field_type *struct_decl)
+ struct ctf_field_type_struct *struct_decl)
{
int ret = 0;
static
int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_field_type *variant_decl)
+ struct ctf_field_type_variant *variant_decl)
{
int ret = 0;
static
int visit_struct_decl(struct ctx *ctx, const char *name,
- struct bt_list_head *decl_list, int has_body,
- struct bt_list_head *min_align,
- struct bt_field_type **struct_decl)
+ struct bt_list_head *decl_list, int has_body,
+ struct bt_list_head *min_align,
+ struct ctf_field_type_struct **struct_decl)
{
int ret = 0;
+ BT_ASSERT(struct_decl);
*struct_decl = NULL;
/* For named struct (without body), lookup in declaration scope */
if (!has_body) {
- _BT_FIELD_TYPE_INIT(struct_decl_copy);
-
if (!name) {
BT_LOGE_STR("Bodyless structure field type: missing name.");
ret = -EPERM;
}
*struct_decl = ctx_decl_scope_lookup_struct(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!*struct_decl) {
BT_LOGE("Cannot find structure field type: name=\"struct %s\"",
name);
ret = -EINVAL;
goto error;
}
-
- /* Make a copy of it */
- struct_decl_copy = bt_field_type_copy(*struct_decl);
- if (!struct_decl_copy) {
- BT_LOGE_STR("Cannot create copy of structure field type.");
- ret = -EINVAL;
- goto error;
- }
-
- BT_MOVE(*struct_decl, struct_decl_copy);
} else {
struct ctf_node *entry_node;
uint64_t min_align_value = 0;
if (name) {
- _BT_FIELD_TYPE_INIT(estruct_decl);
-
- estruct_decl = ctx_decl_scope_lookup_struct(
- ctx->current_scope, name, 1);
- if (estruct_decl) {
- BT_PUT(estruct_decl);
+ if (ctx_decl_scope_lookup_struct(
+ ctx->current_scope, name, 1, false)) {
BT_LOGE("Structure field type already declared in local scope: "
"name=\"struct %s\"", name);
ret = -EINVAL;
}
}
- *struct_decl = bt_field_type_structure_create();
- if (!*struct_decl) {
- BT_LOGE_STR("Cannot create empty structure field type.");
- ret = -ENOMEM;
- goto error;
- }
+ *struct_decl = ctf_field_type_struct_create();
+ BT_ASSERT(*struct_decl);
if (min_align_value != 0) {
- ret = bt_field_type_set_alignment(*struct_decl,
- min_align_value);
- if (ret) {
- BT_LOGE("Cannot set structure field type's alignment: "
- "ret=%d", ret);
- goto error;
- }
+ (*struct_decl)->base.alignment = min_align_value;
}
- ret = ctx_push_scope(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot push scope.");
- goto error;
- }
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(entry_node, decl_list, siblings) {
ret = visit_struct_decl_entry(ctx, entry_node,
return 0;
error:
- BT_PUT(*struct_decl);
-
+ ctf_field_type_destroy((void *) *struct_decl);
+ *struct_decl = NULL;
return ret;
}
static
int visit_variant_decl(struct ctx *ctx, const char *name,
const char *tag, struct bt_list_head *decl_list,
- int has_body, struct bt_field_type **variant_decl)
+ int has_body, struct ctf_field_type_variant **variant_decl)
{
int ret = 0;
- _BT_FIELD_TYPE_INIT(untagged_variant_decl);
+ struct ctf_field_type_variant *untagged_variant_decl = NULL;
+ BT_ASSERT(variant_decl);
*variant_decl = NULL;
/* For named variant (without body), lookup in declaration scope */
if (!has_body) {
- _BT_FIELD_TYPE_INIT(variant_decl_copy);
-
if (!name) {
BT_LOGE_STR("Bodyless variant field type: missing name.");
ret = -EPERM;
untagged_variant_decl =
ctx_decl_scope_lookup_variant(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!untagged_variant_decl) {
BT_LOGE("Cannot find variant field type: name=\"variant %s\"",
name);
ret = -EINVAL;
goto error;
}
-
- /* Make a copy of it */
- variant_decl_copy = bt_field_type_copy(
- untagged_variant_decl);
- if (!variant_decl_copy) {
- BT_LOGE_STR("Cannot create copy of variant field type.");
- ret = -EINVAL;
- goto error;
- }
-
- BT_MOVE(untagged_variant_decl, variant_decl_copy);
} else {
struct ctf_node *entry_node;
if (name) {
- struct bt_field_type *evariant_decl =
- ctx_decl_scope_lookup_struct(ctx->current_scope,
- name, 1);
-
- if (evariant_decl) {
- BT_PUT(evariant_decl);
+ if (ctx_decl_scope_lookup_variant(ctx->current_scope,
+ name, 1, false)) {
BT_LOGE("Variant field type already declared in local scope: "
"name=\"variant %s\"", name);
ret = -EINVAL;
}
}
- untagged_variant_decl = bt_field_type_variant_create(NULL,
- NULL);
- if (!untagged_variant_decl) {
- BT_LOGE_STR("Cannot create empty variant field type.");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot push scope.");
- goto error;
- }
+ untagged_variant_decl = ctf_field_type_variant_create();
+ BT_ASSERT(untagged_variant_decl);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(entry_node, decl_list, siblings) {
ret = visit_variant_decl_entry(ctx, entry_node,
* return untagged variant.
*/
if (!tag) {
- BT_MOVE(*variant_decl, untagged_variant_decl);
+ *variant_decl = untagged_variant_decl;
+ untagged_variant_decl = NULL;
} else {
/*
* At this point, we have a fresh untagged variant; nobody
goto error;
}
- ret = bt_field_type_variant_set_tag_name(
- untagged_variant_decl, tag_no_underscore);
+ g_string_assign(untagged_variant_decl->tag_ref,
+ tag_no_underscore);
free(tag_no_underscore);
- if (ret) {
- BT_LOGE("Cannot set variant field type's tag name: "
- "tag-name=\"%s\"", tag);
- goto error;
- }
-
- BT_MOVE(*variant_decl, untagged_variant_decl);
+ *variant_decl = untagged_variant_decl;
+ untagged_variant_decl = NULL;
}
BT_ASSERT(!untagged_variant_decl);
BT_ASSERT(*variant_decl);
-
return 0;
error:
- BT_PUT(untagged_variant_decl);
- BT_PUT(*variant_decl);
-
+ ctf_field_type_destroy((void *) untagged_variant_decl);
+ untagged_variant_decl = NULL;
+ ctf_field_type_destroy((void *) *variant_decl);
+ *variant_decl = NULL;
return ret;
}
+struct uori {
+ bool is_signed;
+ union {
+ uint64_t u;
+ uint64_t i;
+ } value;
+};
+
static
int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator,
- struct bt_field_type *enum_decl, int64_t *last, bt_bool is_signed)
+ struct ctf_field_type_enum *enum_decl, struct uori *last)
{
int ret = 0;
int nr_vals = 0;
struct ctf_node *iter;
- int64_t start = 0, end = 0;
+ struct uori start = {
+ .is_signed = false,
+ .value.u = 0,
+ };
+ struct uori end = {
+ .is_signed = false,
+ .value.u = 0,
+ };
const char *label = enumerator->u.enumerator.id;
const char *effective_label = label;
struct bt_list_head *values = &enumerator->u.enumerator.values;
bt_list_for_each_entry(iter, values, siblings) {
- int64_t *target;
+ struct uori *target;
if (iter->type != NODE_UNARY_EXPRESSION) {
_BT_LOGE_NODE(iter,
switch (iter->u.unary_expression.type) {
case UNARY_SIGNED_CONSTANT:
- *target = iter->u.unary_expression.u.signed_constant;
+ target->is_signed = true;
+ target->value.i =
+ iter->u.unary_expression.u.signed_constant;
break;
case UNARY_UNSIGNED_CONSTANT:
- *target = (int64_t)
+ target->is_signed = false;
+ target->value.u =
iter->u.unary_expression.u.unsigned_constant;
break;
default:
end = start;
}
- *last = end + 1;
+ if (end.is_signed) {
+ last->value.i = end.value.i + 1;
+ } else {
+ last->value.u = end.value.u + 1;
+ }
if (label[0] == '_') {
/*
effective_label = &label[1];
}
- if (is_signed) {
- ret = bt_field_type_enumeration_signed_add_mapping(enum_decl,
- effective_label, start, end);
- } else {
- ret = bt_field_type_enumeration_unsigned_add_mapping(enum_decl,
- effective_label, (uint64_t) start, (uint64_t) end);
- }
- if (ret) {
- _BT_LOGE_NODE(enumerator,
- "Cannot add mapping to enumeration field type: "
- "label=\"%s\", ret=%d, "
- "start-value-unsigned=%" PRIu64 ", "
- "end-value-unsigned=%" PRIu64, label, ret,
- (uint64_t) start, (uint64_t) end);
- goto error;
- }
-
+ ctf_field_type_enum_append_mapping(enum_decl, effective_label,
+ start.value.u, end.value.u);
return 0;
error:
static
int visit_enum_decl(struct ctx *ctx, const char *name,
- struct ctf_node *container_type,
- struct bt_list_head *enumerator_list,
- int has_body,
- struct bt_field_type **enum_decl)
+ struct ctf_node *container_type,
+ struct bt_list_head *enumerator_list,
+ int has_body, struct ctf_field_type_enum **enum_decl)
{
int ret = 0;
GQuark qdummy_id;
- _BT_FIELD_TYPE_INIT(integer_decl);
+ struct ctf_field_type_int *integer_decl = NULL;
+ BT_ASSERT(enum_decl);
*enum_decl = NULL;
/* For named enum (without body), lookup in declaration scope */
if (!has_body) {
- _BT_FIELD_TYPE_INIT(enum_decl_copy);
-
if (!name) {
BT_LOGE_STR("Bodyless enumeration field type: missing name.");
ret = -EPERM;
}
*enum_decl = ctx_decl_scope_lookup_enum(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!*enum_decl) {
BT_LOGE("Cannot find enumeration field type: "
"name=\"enum %s\"", name);
ret = -EINVAL;
goto error;
}
-
- /* Make a copy of it */
- enum_decl_copy = bt_field_type_copy(*enum_decl);
- if (!enum_decl_copy) {
- BT_LOGE_STR("Cannot create copy of enumeration field type.");
- ret = -EINVAL;
- goto error;
- }
-
- BT_PUT(*enum_decl);
- BT_MOVE(*enum_decl, enum_decl_copy);
} else {
struct ctf_node *iter;
- int64_t last_value = 0;
+ struct uori last_value = {
+ .is_signed = false,
+ .value.u = 0,
+ };
if (name) {
- _BT_FIELD_TYPE_INIT(eenum_decl);
-
- eenum_decl = ctx_decl_scope_lookup_enum(
- ctx->current_scope, name, 1);
- if (eenum_decl) {
- BT_PUT(eenum_decl);
+ if (ctx_decl_scope_lookup_enum(ctx->current_scope,
+ name, 1, false)) {
BT_LOGE("Enumeration field type already declared in local scope: "
"name=\"enum %s\"", name);
ret = -EINVAL;
}
if (!container_type) {
- integer_decl = ctx_decl_scope_lookup_alias(
- ctx->current_scope, "int", -1);
+ integer_decl = (void *) ctx_decl_scope_lookup_alias(
+ ctx->current_scope, "int", -1, true);
if (!integer_decl) {
BT_LOGE_STR("Cannot find implicit `int` field type alias for enumeration field type.");
ret = -EINVAL;
}
} else {
ret = visit_type_declarator(ctx, container_type,
- &qdummy_id, NULL, &integer_decl, NULL);
+ &qdummy_id, NULL, (void *) &integer_decl,
+ NULL);
if (ret) {
BT_ASSERT(!integer_decl);
ret = -EINVAL;
BT_ASSERT(integer_decl);
- if (!bt_field_type_is_integer(integer_decl)) {
+ if (integer_decl->base.base.id != CTF_FIELD_TYPE_ID_INT) {
BT_LOGE("Container field type for enumeration field type is not an integer field type: "
- "ft-id=%s",
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(integer_decl)));
+ "ft-id=%d", integer_decl->base.base.id);
ret = -EINVAL;
goto error;
}
- *enum_decl = bt_field_type_enumeration_create(integer_decl);
- if (!*enum_decl) {
- BT_LOGE_STR("Cannot create enumeration field type.");
- ret = -ENOMEM;
- goto error;
- }
+ *enum_decl = ctf_field_type_enum_create();
+ BT_ASSERT(*enum_decl);
+ (*enum_decl)->base.base.base.alignment =
+ integer_decl->base.base.alignment;
+ ctf_field_type_int_copy_content((void *) *enum_decl,
+ (void *) integer_decl);
+ last_value.is_signed = (*enum_decl)->base.is_signed;
bt_list_for_each_entry(iter, enumerator_list, siblings) {
ret = visit_enum_decl_entry(ctx, iter, *enum_decl,
- &last_value,
- bt_field_type_integer_is_signed(integer_decl));
+ &last_value);
if (ret) {
_BT_LOGE_NODE(iter,
"Cannot visit enumeration field type entry: "
}
}
- BT_PUT(integer_decl);
-
- return 0;
+ goto end;
error:
- BT_PUT(integer_decl);
- BT_PUT(*enum_decl);
+ ctf_field_type_destroy((void *) *enum_decl);
+ *enum_decl = NULL;
+end:
+ ctf_field_type_destroy((void *) integer_decl);
+ integer_decl = NULL;
return ret;
}
static
int visit_type_specifier(struct ctx *ctx,
- struct ctf_node *type_specifier_list,
- struct bt_field_type **decl)
+ struct ctf_node *type_specifier_list,
+ struct ctf_field_type **decl)
{
int ret = 0;
GString *str = NULL;
- _BT_FIELD_TYPE_INIT(decl_copy);
*decl = NULL;
str = g_string_new("");
goto error;
}
- *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1);
+ *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1,
+ true);
if (!*decl) {
_BT_LOGE_NODE(type_specifier_list,
"Cannot find type alias: name=\"%s\"", str->str);
goto error;
}
- /* Make a copy of the type declaration */
- decl_copy = bt_field_type_copy(*decl);
- if (!decl_copy) {
- _BT_LOGE_NODE(type_specifier_list,
- "Cannot create field type copy.");
- ret = -EINVAL;
- goto error;
- }
-
- BT_MOVE(*decl, decl_copy);
- (void) g_string_free(str, TRUE);
- str = NULL;
-
- return 0;
+ goto end;
error:
+ ctf_field_type_destroy(*decl);
+ *decl = NULL;
+
+end:
if (str) {
- (void) g_string_free(str, TRUE);
+ g_string_free(str, TRUE);
}
- BT_PUT(*decl);
-
return ret;
}
static
int visit_integer_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_field_type **integer_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_type_int **integer_decl)
{
int set = 0;
int ret = 0;
- bt_bool signedness = 0;
+ int signedness = 0;
struct ctf_node *expression;
uint64_t alignment = 0, size = 0;
- struct bt_clock_class *mapped_clock = NULL;
- enum bt_string_encoding encoding = BT_STRING_ENCODING_NONE;
- enum bt_integer_base base = BT_INTEGER_BASE_DECIMAL;
- enum bt_byte_order byte_order =
- bt_trace_get_native_byte_order(ctx->trace);
+ struct bt_clock_class *mapped_clock_class = NULL;
+ enum ctf_encoding encoding = CTF_ENCODING_NONE;
+ enum bt_field_type_integer_preferred_display_base base =
+ BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
+ enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
*integer_decl = NULL;
}
byte_order = get_real_byte_order(ctx, right);
- if (byte_order == BT_BYTE_ORDER_UNKNOWN) {
+ if (byte_order == -1) {
_BT_LOGE_NODE(right,
"Invalid `byte_order` attribute in integer field type: "
"ret=%d", ret);
switch (constant) {
case 2:
- base = BT_INTEGER_BASE_BINARY;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
break;
case 8:
- base = BT_INTEGER_BASE_OCTAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
break;
case 10:
- base = BT_INTEGER_BASE_DECIMAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
break;
case 16:
- base = BT_INTEGER_BASE_HEXADECIMAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
break;
default:
_BT_LOGE_NODE(right,
!strcmp(s_right, "d") ||
!strcmp(s_right, "i") ||
!strcmp(s_right, "u")) {
- base = BT_INTEGER_BASE_DECIMAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
} else if (!strcmp(s_right, "hexadecimal") ||
!strcmp(s_right, "hex") ||
!strcmp(s_right, "x") ||
!strcmp(s_right, "X") ||
!strcmp(s_right, "p")) {
- base = BT_INTEGER_BASE_HEXADECIMAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
} else if (!strcmp(s_right, "octal") ||
!strcmp(s_right, "oct") ||
!strcmp(s_right, "o")) {
- base = BT_INTEGER_BASE_OCTAL;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
} else if (!strcmp(s_right, "binary") ||
!strcmp(s_right, "b")) {
- base = BT_INTEGER_BASE_BINARY;
+ base = BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
} else {
_BT_LOGE_NODE(right,
"Unexpected unary expression for integer field type's `base` attribute: "
if (!strcmp(s_right, "UTF8") ||
!strcmp(s_right, "utf8") ||
!strcmp(s_right, "utf-8") ||
- !strcmp(s_right, "UTF-8")) {
- encoding = BT_STRING_ENCODING_UTF8;
- } else if (!strcmp(s_right, "ASCII") ||
+ !strcmp(s_right, "UTF-8") ||
+ !strcmp(s_right, "ASCII") ||
!strcmp(s_right, "ascii")) {
- encoding = BT_STRING_ENCODING_ASCII;
+ encoding = CTF_ENCODING_UTF8;
} else if (!strcmp(s_right, "none")) {
- encoding = BT_STRING_ENCODING_NONE;
+ encoding = CTF_ENCODING_NONE;
} else {
_BT_LOGE_NODE(right,
"Invalid `encoding` attribute in integer field type: "
continue;
}
- mapped_clock = bt_trace_get_clock_class_by_name(
- ctx->trace, clock_name);
- if (!mapped_clock) {
+ mapped_clock_class =
+ ctf_trace_class_borrow_clock_class_by_name(
+ ctx->ctf_tc, clock_name);
+ if (!mapped_clock_class) {
_BT_LOGE_NODE(right,
"Invalid `map` attribute in integer field type: "
"cannot find clock class at this point: name=\"%s\"",
}
}
- *integer_decl = bt_field_type_integer_create((unsigned int) size);
- if (!*integer_decl) {
- BT_LOGE_STR("Cannot create integer field type.");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = bt_field_type_integer_set_is_signed(*integer_decl, signedness);
- ret |= bt_field_type_integer_set_base(*integer_decl, base);
- ret |= bt_field_type_integer_set_encoding(*integer_decl, encoding);
- ret |= bt_field_type_set_alignment(*integer_decl,
- (unsigned int) alignment);
- ret |= bt_field_type_set_byte_order(*integer_decl, byte_order);
-
- if (mapped_clock) {
- /* Move clock */
- ret |= bt_field_type_integer_set_mapped_clock_class(
- *integer_decl, mapped_clock);
- bt_put(mapped_clock);
- mapped_clock = NULL;
- }
-
- if (ret) {
- BT_LOGE_STR("Cannot configure integer field type.");
- ret = -EINVAL;
- goto error;
- }
-
+ *integer_decl = ctf_field_type_int_create();
+ BT_ASSERT(*integer_decl);
+ (*integer_decl)->base.base.alignment = alignment;
+ (*integer_decl)->base.byte_order = byte_order;
+ (*integer_decl)->base.size = size;
+ (*integer_decl)->is_signed = (signedness > 0);
+ (*integer_decl)->disp_base = base;
+ (*integer_decl)->encoding = encoding;
+ (*integer_decl)->mapped_clock_class = bt_get(mapped_clock_class);
return 0;
error:
- if (mapped_clock) {
- bt_put(mapped_clock);
- }
-
- BT_PUT(*integer_decl);
-
+ ctf_field_type_destroy((void *) *integer_decl);
+ *integer_decl = NULL;
return ret;
}
static
int visit_floating_point_number_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_field_type **float_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_type_float **float_decl)
{
int set = 0;
int ret = 0;
struct ctf_node *expression;
uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
- enum bt_byte_order byte_order =
- bt_trace_get_native_byte_order(ctx->trace);
+ enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
*float_decl = NULL;
}
byte_order = get_real_byte_order(ctx, right);
- if (byte_order == BT_BYTE_ORDER_UNKNOWN) {
+ if (byte_order == -1) {
_BT_LOGE_NODE(right,
"Invalid `byte_order` attribute in floating point number field type: "
"ret=%d", ret);
goto error;
}
+ if (mant_dig != 24 && mant_dig != 53) {
+ BT_LOGE_STR("`mant_dig` attribute: expecting 24 or 53.");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (mant_dig == 24 && exp_dig != 8) {
+ BT_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (mant_dig == 53 && exp_dig != 11) {
+ BT_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
+ ret = -EPERM;
+ goto error;
+ }
+
if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
if ((mant_dig + exp_dig) % CHAR_BIT) {
/* Bit-packed alignment */
}
}
- *float_decl = bt_field_type_floating_point_create();
- if (!*float_decl) {
- BT_LOGE_STR("Cannot create floating point number field type.");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = bt_field_type_floating_point_set_exponent_digits(
- *float_decl, exp_dig);
- ret |= bt_field_type_floating_point_set_mantissa_digits(
- *float_decl, mant_dig);
- ret |= bt_field_type_set_byte_order(*float_decl, byte_order);
- ret |= bt_field_type_set_alignment(*float_decl, alignment);
- if (ret) {
- BT_LOGE_STR("Cannot configure floating point number field type.");
- ret = -EINVAL;
- goto error;
- }
-
+ *float_decl = ctf_field_type_float_create();
+ BT_ASSERT(*float_decl);
+ (*float_decl)->base.base.alignment = alignment;
+ (*float_decl)->base.byte_order = byte_order;
+ (*float_decl)->base.size = mant_dig + exp_dig;
return 0;
error:
- BT_PUT(*float_decl);
-
+ ctf_field_type_destroy((void *) *float_decl);
+ *float_decl = NULL;
return ret;
}
static
int visit_string_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_field_type **string_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_type_string **string_decl)
{
int set = 0;
int ret = 0;
struct ctf_node *expression;
- enum bt_string_encoding encoding = BT_STRING_ENCODING_UTF8;
+ enum ctf_encoding encoding = CTF_ENCODING_UTF8;
*string_decl = NULL;
if (!strcmp(s_right, "UTF8") ||
!strcmp(s_right, "utf8") ||
!strcmp(s_right, "utf-8") ||
- !strcmp(s_right, "UTF-8")) {
- encoding = BT_STRING_ENCODING_UTF8;
- } else if (!strcmp(s_right, "ASCII") ||
+ !strcmp(s_right, "UTF-8") ||
+ !strcmp(s_right, "ASCII") ||
!strcmp(s_right, "ascii")) {
- encoding = BT_STRING_ENCODING_ASCII;
+ encoding = CTF_ENCODING_UTF8;
} else if (!strcmp(s_right, "none")) {
- encoding = BT_STRING_ENCODING_NONE;
+ encoding = CTF_ENCODING_NONE;
} else {
_BT_LOGE_NODE(right,
"Invalid `encoding` attribute in string field type: "
}
}
- *string_decl = bt_field_type_string_create();
- if (!*string_decl) {
- BT_LOGE_STR("Cannot create string field type.");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = bt_field_type_string_set_encoding(*string_decl, encoding);
- if (ret) {
- BT_LOGE_STR("Cannot configure string field type.");
- ret = -EINVAL;
- goto error;
- }
-
+ *string_decl = ctf_field_type_string_create();
+ BT_ASSERT(*string_decl);
+ (*string_decl)->encoding = encoding;
return 0;
error:
- BT_PUT(*string_decl);
-
+ ctf_field_type_destroy((void *) *string_decl);
+ *string_decl = NULL;
return ret;
}
static
int visit_type_specifier_list(struct ctx *ctx,
- struct ctf_node *ts_list,
- struct bt_field_type **decl)
+ struct ctf_node *ts_list, struct ctf_field_type **decl)
{
int ret = 0;
struct ctf_node *first, *node;
switch (first->u.type_specifier.type) {
case TYPESPEC_INTEGER:
ret = visit_integer_decl(ctx, &node->u.integer.expressions,
- decl);
+ (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
break;
case TYPESPEC_FLOATING_POINT:
ret = visit_floating_point_number_decl(ctx,
- &node->u.floating_point.expressions, decl);
+ &node->u.floating_point.expressions, (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
break;
case TYPESPEC_STRING:
ret = visit_string_decl(ctx,
- &node->u.string.expressions, decl);
+ &node->u.string.expressions, (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
ret = visit_struct_decl(ctx, node->u._struct.name,
&node->u._struct.declaration_list,
node->u._struct.has_body,
- &node->u._struct.min_align, decl);
+ &node->u._struct.min_align, (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
ret = visit_variant_decl(ctx, node->u.variant.name,
node->u.variant.choice,
&node->u.variant.declaration_list,
- node->u.variant.has_body, decl);
+ node->u.variant.has_body, (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
ret = visit_enum_decl(ctx, node->u._enum.enum_id,
node->u._enum.container_type,
&node->u._enum.enumerator_list,
- node->u._enum.has_body, decl);
+ node->u._enum.has_body, (void *) decl);
if (ret) {
BT_ASSERT(!*decl);
goto error;
}
BT_ASSERT(*decl);
-
return 0;
error:
- BT_PUT(*decl);
-
+ ctf_field_type_destroy((void *) *decl);
+ *decl = NULL;
return ret;
}
static
int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
- struct bt_event_class *event_class, int64_t *stream_id,
- int *set)
+ struct ctf_event_class *event_class, uint64_t *stream_id,
+ int *set)
{
int ret = 0;
char *left = NULL;
- _BT_FIELD_TYPE_INIT(decl);
switch (node->type) {
case NODE_TYPEDEF:
if (!strcmp(left, "name")) {
/* This is already known at this stage */
if (_IS_SET(set, _EVENT_NAME_SET)) {
- _BT_LOGE_DUP_ATTR(node, "name",
- "event class");
+ _BT_LOGE_DUP_ATTR(node, "name", "event class");
ret = -EPERM;
goto error;
}
int64_t id = -1;
if (_IS_SET(set, _EVENT_ID_SET)) {
- _BT_LOGE_DUP_ATTR(node, "id",
- "event class");
+ _BT_LOGE_DUP_ATTR(node, "id", "event class");
ret = -EPERM;
goto error;
}
goto error;
}
- ret = bt_event_class_set_id(event_class, id);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's ID: "
- "id=%" PRId64, id);
- goto error;
- }
-
+ event_class->id = id;
_SET(set, _EVENT_ID_SET);
} else if (!strcmp(left, "stream_id")) {
if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- (uint64_t *) stream_id);
+ stream_id);
+
/*
* Only read "stream_id" if get_unary_unsigned()
* succeeded.
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &event_class->spec_context_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create event class's context field type.");
goto error;
}
- BT_ASSERT(decl);
- ret = bt_event_class_set_context_field_type(
- event_class, decl);
- BT_PUT(decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's context field type.");
- goto error;
- }
-
+ BT_ASSERT(event_class->spec_context_ft);
_SET(set, _EVENT_CONTEXT_SET);
} else if (!strcmp(left, "fields")) {
if (_IS_SET(set, _EVENT_FIELDS_SET)) {
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &event_class->payload_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create event class's payload field type.");
goto error;
}
- BT_ASSERT(decl);
- ret = bt_event_class_set_payload_field_type(
- event_class, decl);
- BT_PUT(decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's payload field type.");
- goto error;
- }
-
+ BT_ASSERT(event_class->payload_ft);
_SET(set, _EVENT_FIELDS_SET);
} else if (!strcmp(left, "loglevel")) {
uint64_t loglevel_value;
- enum bt_event_class_log_level log_level =
- BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
+ enum bt_event_class_log_level log_level = -1;
- if (_IS_SET(set, _EVENT_LOGLEVEL_SET)) {
+ if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
_BT_LOGE_DUP_ATTR(node, "loglevel",
"event class");
ret = -EPERM;
"log-level=%" PRIu64, loglevel_value);
}
- if (log_level != BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
- ret = bt_event_class_set_log_level(
- event_class, log_level);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's log level.");
- goto error;
- }
+ if (log_level != -1) {
+ event_class->log_level = log_level;
}
- _SET(set, _EVENT_LOGLEVEL_SET);
+ _SET(set, _EVENT_LOG_LEVEL_SET);
} else if (!strcmp(left, "model.emf.uri")) {
char *right;
_BT_LOGW_NODE(node,
"Not setting event class's EMF URI because it's empty.");
} else {
- ret = bt_event_class_set_emf_uri(
- event_class, right);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's EMF URI.");
- goto error;
- }
+ g_string_assign(event_class->emf_uri,
+ right);
}
g_free(right);
goto error;
}
- return 0;
+ goto end;
error:
if (left) {
g_free(left);
}
- BT_PUT(decl);
-
+end:
return ret;
}
error:
g_free(left);
-
- return NULL;
-}
-
-static
-int reset_event_decl_types(struct ctx *ctx,
- struct bt_event_class *event_class)
-{
- int ret = 0;
-
- /* Context type. */
- ret = bt_event_class_set_context_field_type(event_class, NULL);
- if (ret) {
- BT_LOGE("Cannot reset initial event class's context field type: "
- "event-name=\"%s\"",
- bt_event_class_get_name(event_class));
- goto end;
- }
-
- /* Event payload. */
- ret = bt_event_class_set_payload_field_type(event_class, NULL);
- if (ret) {
- BT_LOGE("Cannot reset initial event class's payload field type: "
- "event-name=\"%s\"",
- bt_event_class_get_name(event_class));
- goto end;
- }
-end:
- return ret;
-}
-
-static
-int reset_stream_decl_types(struct ctx *ctx,
- struct bt_stream_class *stream_class)
-{
- int ret = 0;
-
- /* Packet context. */
- ret = bt_stream_class_set_packet_context_field_type(stream_class, NULL);
- if (ret) {
- BT_LOGE_STR("Cannot reset initial stream class's packet context field type.");
- goto end;
- }
-
- /* Event header. */
- ret = bt_stream_class_set_event_header_field_type(stream_class, NULL);
- if (ret) {
- BT_LOGE_STR("Cannot reset initial stream class's event header field type.");
- goto end;
- }
-
- /* Event context. */
- ret = bt_stream_class_set_event_context_field_type(stream_class, NULL);
- if (ret) {
- BT_LOGE_STR("Cannot reset initial stream class's event context field type.");
- goto end;
- }
-end:
- return ret;
-}
-
-static
-struct bt_stream_class *create_reset_stream_class(struct ctx *ctx)
-{
- int ret;
- struct bt_stream_class *stream_class;
-
- stream_class = bt_stream_class_create(NULL);
- if (!stream_class) {
- BT_LOGE_STR("Cannot create empty stream class.");
- goto error;
- }
-
- /*
- * Set packet context, event header, and event context to NULL to
- * override the default ones.
- */
- ret = reset_stream_decl_types(ctx, stream_class);
- if (ret) {
- goto error;
- }
-
- return stream_class;
-
-error:
- BT_PUT(stream_class);
-
return NULL;
}
{
int ret = 0;
int set = 0;
- int64_t event_id;
struct ctf_node *iter;
- int64_t stream_id = -1;
+ uint64_t stream_id = 0;
char *event_name = NULL;
- struct bt_event_class *event_class = NULL;
- struct bt_event_class *eevent_class;
- struct bt_stream_class *stream_class = NULL;
+ struct ctf_event_class *event_class = NULL;
+ struct ctf_stream_class *stream_class = NULL;
struct bt_list_head *decl_list = &node->u.event.declaration_list;
bool pop_scope = false;
goto error;
}
- event_class = bt_event_class_create(event_name);
-
- /*
- * Unset context and fields to override the default ones.
- */
- ret = reset_event_decl_types(ctx, event_class);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot reset event class's field types: "
- "ret=%d", ret);
- goto error;
- }
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot push scope.");
- goto error;
- }
-
+ event_class = ctf_event_class_create();
+ BT_ASSERT(event_class);
+ g_string_assign(event_class->name, event_name);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
pop_scope = true;
bt_list_for_each_entry(iter, decl_list, siblings) {
}
if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
- GList *keys = NULL;
- int64_t *new_stream_id;
- struct bt_stream_class *new_stream_class;
- size_t stream_class_count =
- g_hash_table_size(ctx->stream_classes) +
- bt_trace_get_stream_class_count(ctx->trace);
-
/*
* Allow missing stream_id if there is only a single
* stream class.
*/
- switch (stream_class_count) {
+ switch (ctx->ctf_tc->stream_classes->len) {
case 0:
/* Create implicit stream class if there's none */
stream_id = 0;
- new_stream_class = create_reset_stream_class(ctx);
- if (!new_stream_class) {
- _BT_LOGE_NODE(node,
- "Cannot create empty stream class.");
- ret = -EINVAL;
- goto error;
- }
-
- ret = bt_stream_class_set_id(new_stream_class,
- stream_id);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set stream class's ID: "
- "id=0, ret=%d", ret);
- BT_PUT(new_stream_class);
- goto error;
- }
-
- new_stream_id = g_new0(int64_t, 1);
- if (!new_stream_id) {
- BT_LOGE_STR("Failed to allocate a int64_t.");
- ret = -ENOMEM;
- goto error;
- }
-
- *new_stream_id = stream_id;
-
- /* Move reference to visitor's context */
- g_hash_table_insert(ctx->stream_classes,
- new_stream_id, new_stream_class);
- new_stream_id = NULL;
- new_stream_class = NULL;
+ stream_class = ctf_stream_class_create();
+ BT_ASSERT(stream_class);
+ stream_class->id = stream_id;
+ g_ptr_array_add(ctx->ctf_tc->stream_classes,
+ stream_class);
+ stream_class = stream_class;
break;
case 1:
/* Single stream class: get its ID */
- if (g_hash_table_size(ctx->stream_classes) == 1) {
- keys = g_hash_table_get_keys(ctx->stream_classes);
- stream_id = *((int64_t *) keys->data);
- g_list_free(keys);
- } else {
- BT_ASSERT(bt_trace_get_stream_class_count(
- ctx->trace) == 1);
- stream_class =
- bt_trace_get_stream_class_by_index(
- ctx->trace, 0);
- BT_ASSERT(stream_class);
- stream_id = bt_stream_class_get_id(
- stream_class);
- BT_PUT(stream_class);
- }
+ stream_class = ctx->ctf_tc->stream_classes->pdata[0];
+ stream_id = stream_class->id;
break;
default:
_BT_LOGE_NODE(node,
}
}
- BT_ASSERT(stream_id >= 0);
-
/* We have the stream ID now; get the stream class if found */
- stream_class = g_hash_table_lookup(ctx->stream_classes, &stream_id);
- bt_get(stream_class);
if (!stream_class) {
- stream_class = bt_trace_get_stream_class_by_id(ctx->trace,
- stream_id);
+ stream_class = ctf_trace_class_borrow_stream_class_by_id(
+ ctx->ctf_tc, stream_id);
if (!stream_class) {
_BT_LOGE_NODE(node,
"Cannot find stream class at this point: "
if (!_IS_SET(&set, _EVENT_ID_SET)) {
/* Allow only one event without ID per stream */
- if (bt_stream_class_get_event_class_count(stream_class) !=
- 0) {
+ if (stream_class->event_classes->len != 0) {
_BT_LOGE_NODE(node,
"Missing `id` attribute in event class.");
ret = -EPERM;
}
/* Automatic ID */
- ret = bt_event_class_set_id(event_class, 0);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set event class's ID: id=0, ret=%d",
- ret);
- goto error;
- }
+ event_class->id = 0;
}
- event_id = bt_event_class_get_id(event_class);
- if (event_id < 0) {
- _BT_LOGE_NODE(node, "Cannot get event class's ID.");
- ret = -EINVAL;
- goto error;
- }
-
- eevent_class = bt_stream_class_get_event_class_by_id(stream_class,
- event_id);
- if (eevent_class) {
- BT_PUT(eevent_class);
+ if (ctf_stream_class_borrow_event_class_by_id(stream_class,
+ event_class->id)) {
_BT_LOGE_NODE(node,
"Duplicate event class (same ID) in the same stream class: "
- "id=%" PRId64, event_id);
+ "id=%" PRId64, event_class->id);
ret = -EEXIST;
goto error;
}
- ret = bt_stream_class_add_event_class(stream_class, event_class);
- BT_PUT(event_class);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot add event class to stream class: ret=%d", ret);
- goto error;
- }
-
+ ctf_stream_class_append_event_class(stream_class, event_class);
+ event_class = NULL;
goto end;
error:
- bt_put(event_class);
+ ctf_event_class_destroy(event_class);
+ event_class = NULL;
+
+ if (ret >= 0) {
+ ret = -1;
+ }
end:
if (pop_scope) {
ctx_pop_scope(ctx);
}
- g_free(event_name);
- bt_put(stream_class);
+ if (event_name) {
+ g_free(event_name);
+ }
+
return ret;
}
static
int auto_map_field_to_trace_clock_class(struct ctx *ctx,
- struct bt_field_type *ft)
+ struct ctf_field_type *ft)
{
struct bt_clock_class *clock_class_to_map_to = NULL;
- struct bt_clock_class *mapped_clock_class = NULL;
+ struct ctf_field_type_int *int_ft = (void *) ft;
int ret = 0;
- int64_t clock_class_count;
+ uint64_t clock_class_count;
+
+ if (!ft) {
+ goto end;
+ }
- if (!ft || !bt_field_type_is_integer(ft)) {
+ if (ft->id != CTF_FIELD_TYPE_ID_INT &&
+ ft->id != CTF_FIELD_TYPE_ID_ENUM) {
goto end;
}
- mapped_clock_class =
- bt_field_type_integer_get_mapped_clock_class(ft);
- if (mapped_clock_class) {
+ if (int_ft->mapped_clock_class) {
+ /* Already mapped */
goto end;
}
- clock_class_count = bt_trace_get_clock_class_count(ctx->trace);
- BT_ASSERT(clock_class_count >= 0);
+ clock_class_count = ctx->ctf_tc->clock_classes->len;
switch (clock_class_count) {
case 0:
/*
- * No clock class exists in the trace at this
- * point. Create an implicit one at 1 GHz,
- * named `default`, and use this clock class.
+ * No clock class exists in the trace at this point. Create an
+ * implicit one at 1 GHz, named `default`, and use this clock
+ * class.
*/
- clock_class_to_map_to = bt_clock_class_create("default",
- 1000000000);
- if (!clock_class_to_map_to) {
- BT_LOGE_STR("Cannot create a clock class.");
- ret = -1;
- goto end;
- }
-
- ret = bt_trace_add_clock_class(ctx->trace,
- clock_class_to_map_to);
- if (ret) {
- BT_LOGE_STR("Cannot add clock class to trace.");
- goto end;
- }
+ clock_class_to_map_to = bt_clock_class_create();
+ BT_ASSERT(clock_class_to_map_to);
+ ret = bt_clock_class_set_frequency(clock_class_to_map_to,
+ UINT64_C(1000000000));
+ BT_ASSERT(ret == 0);
+ ret = bt_clock_class_set_name(clock_class_to_map_to,
+ "default");
+ BT_ASSERT(ret == 0);
+ g_ptr_array_add(ctx->ctf_tc->clock_classes,
+ bt_get(clock_class_to_map_to));
break;
case 1:
/*
- * Only one clock class exists in the trace at
- * this point: use this one.
+ * Only one clock class exists in the trace at this point: use
+ * this one.
*/
clock_class_to_map_to =
- bt_trace_get_clock_class_by_index(ctx->trace, 0);
- BT_ASSERT(clock_class_to_map_to);
+ bt_get(ctx->ctf_tc->clock_classes->pdata[0]);
break;
default:
/*
- * Timestamp field not mapped to a clock class
- * and there's more than one clock class in the
- * trace: this is an error.
+ * Timestamp field not mapped to a clock class and there's more
+ * than one clock class in the trace: this is an error.
*/
BT_LOGE_STR("Timestamp field found with no mapped clock class, "
"but there's more than one clock class in the trace at this point.");
}
BT_ASSERT(clock_class_to_map_to);
- ret = bt_field_type_integer_set_mapped_clock_class(ft,
- clock_class_to_map_to);
- if (ret) {
- BT_LOGE("Cannot map field type's field to trace's clock class: "
- "clock-class-name=\"%s\", ret=%d",
- bt_clock_class_get_name(clock_class_to_map_to),
- ret);
- goto end;
- }
+ int_ft->mapped_clock_class = bt_get(clock_class_to_map_to);
end:
bt_put(clock_class_to_map_to);
- bt_put(mapped_clock_class);
return ret;
}
static
int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
- struct bt_field_type *root_ft, const char *field_name)
+ struct ctf_field_type *root_ft, const char *field_name)
{
int ret = 0;
- int64_t i, count;
+ uint64_t i, count;
+ struct ctf_field_type_struct *struct_ft = (void *) root_ft;
+ struct ctf_field_type_variant *var_ft = (void *) root_ft;
if (!root_ft) {
goto end;
}
- if (!bt_field_type_is_structure(root_ft) &&
- !bt_field_type_is_variant(root_ft)) {
+ if (root_ft->id != CTF_FIELD_TYPE_ID_STRUCT &&
+ root_ft->id != CTF_FIELD_TYPE_ID_VARIANT) {
goto end;
}
- if (bt_field_type_is_structure(root_ft)) {
- count = bt_field_type_structure_get_field_count(root_ft);
+ if (root_ft->id == CTF_FIELD_TYPE_ID_STRUCT) {
+ count = struct_ft->members->len;
} else {
- count = bt_field_type_variant_get_field_count(root_ft);
+ count = var_ft->options->len;
}
- BT_ASSERT(count >= 0);
-
for (i = 0; i < count; i++) {
- _BT_FIELD_TYPE_INIT(ft);
- const char *name;
+ struct ctf_named_field_type *named_ft = NULL;
- if (bt_field_type_is_structure(root_ft)) {
- ret = bt_field_type_structure_get_field_by_index(
- root_ft, &name, &ft, i);
- } else if (bt_field_type_is_variant(root_ft)) {
- ret = bt_field_type_variant_get_field_by_index(
- root_ft, &name, &ft, i);
+ if (root_ft->id == CTF_FIELD_TYPE_ID_STRUCT) {
+ named_ft = ctf_field_type_struct_borrow_member_by_index(
+ struct_ft, i);
+ } else if (root_ft->id == CTF_FIELD_TYPE_ID_VARIANT) {
+ named_ft = ctf_field_type_variant_borrow_option_by_index(
+ var_ft, i);
}
- BT_ASSERT(ret == 0);
-
- if (strcmp(name, field_name) == 0) {
- ret = auto_map_field_to_trace_clock_class(ctx, ft);
+ if (strcmp(named_ft->name->str, field_name) == 0) {
+ ret = auto_map_field_to_trace_clock_class(ctx,
+ named_ft->ft);
if (ret) {
BT_LOGE("Cannot automatically map field to trace's clock class: "
"field-name=\"%s\"", field_name);
- bt_put(ft);
goto end;
}
}
- ret = auto_map_fields_to_trace_clock_class(ctx, ft, field_name);
- bt_put(ft);
+ ret = auto_map_fields_to_trace_clock_class(ctx, named_ft->ft,
+ field_name);
if (ret) {
BT_LOGE("Cannot automatically map structure or variant field type's fields to trace's clock class: "
"field-name=\"%s\", root-field-name=\"%s\"",
- field_name, name);
+ field_name, named_ft->name->str);
goto end;
}
}
static
int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
- struct bt_stream_class *stream_class, int *set)
+ struct ctf_stream_class *stream_class, int *set)
{
int ret = 0;
char *left = NULL;
- _BT_FIELD_TYPE_INIT(decl);
switch (node->type) {
case NODE_TYPEDEF:
if (!strcmp(left, "id")) {
int64_t id;
- gpointer ptr;
if (_IS_SET(set, _STREAM_ID_SET)) {
_BT_LOGE_DUP_ATTR(node, "id",
ret = get_unary_unsigned(&node->u.ctf_expression.right,
(uint64_t *) &id);
+
/* Only read "id" if get_unary_unsigned() succeeded. */
if (ret || (!ret && id < 0)) {
_BT_LOGE_NODE(node,
goto error;
}
- ptr = g_hash_table_lookup(ctx->stream_classes, &id);
- if (ptr) {
+ if (ctf_trace_class_borrow_stream_class_by_id(
+ ctx->ctf_tc, id)) {
_BT_LOGE_NODE(node,
"Duplicate stream class (same ID): id=%" PRId64,
id);
goto error;
}
- ret = bt_stream_class_set_id(stream_class, id);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set stream class's ID: "
- "id=%" PRId64 ", ret=%d", id, ret);
- goto error;
- }
-
+ stream_class->id = id;
_SET(set, _STREAM_ID_SET);
} else if (!strcmp(left, "event.header")) {
if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &stream_class->event_header_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create stream class's event header field type.");
goto error;
}
- BT_ASSERT(decl);
+ BT_ASSERT(stream_class->event_header_ft);
ret = auto_map_fields_to_trace_clock_class(ctx,
- decl, "timestamp");
+ stream_class->event_header_ft, "timestamp");
if (ret) {
_BT_LOGE_NODE(node,
"Cannot automatically map specific event header field type fields named `timestamp` to trace's clock class.");
goto error;
}
- ret = bt_stream_class_set_event_header_field_type(
- stream_class, decl);
- BT_PUT(decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set stream class's event header field type.");
- goto error;
- }
-
_SET(set, _STREAM_EVENT_HEADER_SET);
} else if (!strcmp(left, "event.context")) {
if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &stream_class->event_common_context_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create stream class's event context field type.");
goto error;
}
- BT_ASSERT(decl);
-
- ret = bt_stream_class_set_event_context_field_type(
- stream_class, decl);
- BT_PUT(decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set stream class's event context field type.");
- goto error;
- }
-
+ BT_ASSERT(stream_class->event_common_context_ft);
_SET(set, _STREAM_EVENT_CONTEXT_SET);
} else if (!strcmp(left, "packet.context")) {
if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &stream_class->packet_context_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create stream class's packet context field type.");
goto error;
}
- BT_ASSERT(decl);
+ BT_ASSERT(stream_class->packet_context_ft);
ret = auto_map_fields_to_trace_clock_class(ctx,
- decl, "timestamp_begin");
+ stream_class->packet_context_ft,
+ "timestamp_begin");
if (ret) {
_BT_LOGE_NODE(node,
"Cannot automatically map specific packet context field type fields named `timestamp_begin` to trace's clock class.");
}
ret = auto_map_fields_to_trace_clock_class(ctx,
- decl, "timestamp_end");
+ stream_class->packet_context_ft,
+ "timestamp_end");
if (ret) {
_BT_LOGE_NODE(node,
"Cannot automatically map specific packet context field type fields named `timestamp_end` to trace's clock class.");
goto error;
}
- ret = bt_stream_class_set_packet_context_field_type(
- stream_class, decl);
- BT_PUT(decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set stream class's packet context field type.");
- goto error;
- }
-
_SET(set, _STREAM_PACKET_CONTEXT_SET);
} else {
_BT_LOGW_NODE(node,
error:
g_free(left);
- BT_PUT(decl);
-
return ret;
}
static
int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
{
- int64_t id;
- int64_t *new_id;
int set = 0;
int ret = 0;
struct ctf_node *iter;
- struct bt_stream_class *stream_class = NULL;
- struct bt_stream_class *existing_stream_class = NULL;
+ struct ctf_stream_class *stream_class = NULL;
struct bt_list_head *decl_list = &node->u.stream.declaration_list;
if (node->visited) {
}
node->visited = TRUE;
- stream_class = create_reset_stream_class(ctx);
- if (!stream_class) {
- _BT_LOGE_NODE(node, "Cannot create empty stream class.");
- ret = -EINVAL;
- goto error;
- }
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot push scope.");
- goto error;
- }
+ stream_class = ctf_stream_class_create();
+ BT_ASSERT(stream_class);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(iter, decl_list, siblings) {
ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
ctx_pop_scope(ctx);
if (_IS_SET(&set, _STREAM_ID_SET)) {
- /* Check that packet header has stream_id field */
- _BT_FIELD_TYPE_INIT(stream_id_decl);
- _BT_FIELD_TYPE_INIT(packet_header_decl);
+ /* Check that packet header has `stream_id` field */
+ struct ctf_named_field_type *named_ft = NULL;
- packet_header_decl =
- bt_trace_get_packet_header_field_type(ctx->trace);
- if (!packet_header_decl) {
+ if (!ctx->ctf_tc->packet_header_ft) {
_BT_LOGE_NODE(node,
"Stream class has a `id` attribute, "
"but trace has no packet header field type.");
goto error;
}
- stream_id_decl =
- bt_field_type_structure_get_field_type_by_name(
- packet_header_decl, "stream_id");
- BT_PUT(packet_header_decl);
- if (!stream_id_decl) {
+ named_ft = ctf_field_type_struct_borrow_member_by_name(
+ (void *) ctx->ctf_tc->packet_header_ft, "stream_id");
+ if (!named_ft) {
_BT_LOGE_NODE(node,
"Stream class has a `id` attribute, "
"but trace's packet header field type has no `stream_id` field.");
goto error;
}
- if (!bt_field_type_is_integer(stream_id_decl)) {
- BT_PUT(stream_id_decl);
+ if (named_ft->ft->id != CTF_FIELD_TYPE_ID_INT &&
+ named_ft->ft->id != CTF_FIELD_TYPE_ID_ENUM) {
_BT_LOGE_NODE(node,
"Stream class has a `id` attribute, "
"but trace's packet header field type's `stream_id` field is not an integer field type.");
goto error;
}
-
- BT_PUT(stream_id_decl);
} else {
/* Allow only _one_ ID-less stream */
- if (g_hash_table_size(ctx->stream_classes) != 0) {
+ if (ctx->ctf_tc->stream_classes->len != 0) {
_BT_LOGE_NODE(node,
"Missing `id` attribute in stream class as there's more than one stream class in the trace.");
ret = -EPERM;
}
/* Automatic ID: 0 */
- ret = bt_stream_class_set_id(stream_class, 0);
- BT_ASSERT(ret == 0);
- }
-
- id = bt_stream_class_get_id(stream_class);
- if (id < 0) {
- _BT_LOGE_NODE(node,
- "Cannot get stream class's ID.");
- ret = -EINVAL;
- goto error;
+ stream_class->id = 0;
}
/*
* Make sure that this stream class's ID is currently unique in
* the trace.
*/
- existing_stream_class = bt_trace_get_stream_class_by_id(ctx->trace,
- id);
- if (g_hash_table_lookup(ctx->stream_classes, &id) ||
- existing_stream_class) {
+ if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
+ stream_class->id)) {
_BT_LOGE_NODE(node,
"Duplicate stream class (same ID): id=%" PRId64,
- id);
+ stream_class->id);
ret = -EINVAL;
goto error;
}
- new_id = g_new0(int64_t, 1);
- if (!new_id) {
- BT_LOGE_STR("Failed to allocate a int64_t.");
- ret = -ENOMEM;
- goto error;
- }
- *new_id = id;
-
- /* Move reference to visitor's context */
- g_hash_table_insert(ctx->stream_classes, new_id,
- stream_class);
+ g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
stream_class = NULL;
goto end;
error:
- bt_put(stream_class);
+ ctf_stream_class_destroy(stream_class);
+ stream_class = NULL;
end:
- bt_put(existing_stream_class);
return ret;
}
{
int ret = 0;
char *left = NULL;
- _BT_FIELD_TYPE_INIT(packet_header_decl);
+ uint64_t val;
switch (node->type) {
case NODE_TYPEDEF:
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- &ctx->trace_major);
+ &val);
if (ret) {
_BT_LOGE_NODE(node,
"Unexpected unary expression for trace's `major` attribute.");
goto error;
}
+ if (val != 1) {
+ _BT_LOGE_NODE(node,
+ "Invalid trace's `minor` attribute: expecting 1.");
+ goto error;
+ }
+
+ ctx->ctf_tc->major = val;
_SET(set, _TRACE_MAJOR_SET);
} else if (!strcmp(left, "minor")) {
if (_IS_SET(set, _TRACE_MINOR_SET)) {
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- &ctx->trace_minor);
+ &val);
if (ret) {
_BT_LOGE_NODE(node,
"Unexpected unary expression for trace's `minor` attribute.");
goto error;
}
+ if (val != 8) {
+ _BT_LOGE_NODE(node,
+ "Invalid trace's `minor` attribute: expecting 8.");
+ goto error;
+ }
+
+ ctx->ctf_tc->minor = val;
_SET(set, _TRACE_MINOR_SET);
} else if (!strcmp(left, "uuid")) {
if (_IS_SET(set, _TRACE_UUID_SET)) {
}
ret = get_unary_uuid(&node->u.ctf_expression.right,
- ctx->trace_uuid);
+ ctx->ctf_tc->uuid);
if (ret) {
_BT_LOGE_NODE(node,
"Invalid trace's `uuid` attribute.");
goto error;
}
- ret = bt_trace_set_uuid(ctx->trace, ctx->trace_uuid);
- if (ret) {
- _BT_LOGE_NODE(node, "Cannot set trace's UUID.");
- goto error;
- }
-
+ ctx->ctf_tc->is_uuid_set = true;
_SET(set, _TRACE_UUID_SET);
} else if (!strcmp(left, "byte_order")) {
- /* Native byte order is already known at this stage */
+ /* Default byte order is already known at this stage */
if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
_BT_LOGE_DUP_ATTR(node, "byte_order",
"trace");
goto error;
}
+ BT_ASSERT(ctx->ctf_tc->default_byte_order != -1);
_SET(set, _TRACE_BYTE_ORDER_SET);
} else if (!strcmp(left, "packet.header")) {
if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &packet_header_decl);
+ &ctx->ctf_tc->packet_header_ft);
if (ret) {
_BT_LOGE_NODE(node,
"Cannot create trace's packet header field type.");
goto error;
}
- BT_ASSERT(packet_header_decl);
- ret = bt_trace_set_packet_header_field_type(ctx->trace,
- packet_header_decl);
- BT_PUT(packet_header_decl);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set trace's packet header field type.");
- goto error;
- }
-
+ BT_ASSERT(ctx->ctf_tc->packet_header_ft);
_SET(set, _TRACE_PACKET_HEADER_SET);
} else {
_BT_LOGW_NODE(node,
error:
g_free(left);
- BT_PUT(packet_header_decl);
-
return ret;
}
goto error;
}
- ret = ctx_push_scope(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot push scope.");
- goto error;
- }
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(iter, decl_list, siblings) {
ret = visit_trace_decl_entry(ctx, iter, &set);
goto error;
}
- ctx->is_trace_visited = TRUE;
+ ctx->is_trace_visited = true;
end:
return 0;
BT_LOGI("Detected LTTng trace from `%s` environment value: "
"tracer-name=\"%s\"",
left, right);
- ctx->is_lttng = 1;
+ ctx->is_lttng = true;
}
}
- ret = bt_trace_set_environment_field_string(
- ctx->trace, left, right);
+ ctf_trace_class_append_env_entry(ctx->ctf_tc,
+ left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
+ right, 0);
g_free(right);
-
- if (ret) {
- _BT_LOGE_NODE(entry_node,
- "Cannot add string environment entry to trace: "
- "name=\"%s\", ret=%d", left, ret);
- goto error;
- }
} else if (is_unary_unsigned(right_head) ||
is_unary_signed(right_head)) {
int64_t v;
goto error;
}
- ret = bt_trace_set_environment_field_integer(
- ctx->trace, left, v);
- if (ret) {
- _BT_LOGE_NODE(entry_node,
- "Cannot add integer environment entry to trace: "
- "name=\"%s\", ret=%d", left, ret);
- goto error;
- }
+ ctf_trace_class_append_env_entry(ctx->ctf_tc,
+ left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
+ NULL, v);
} else {
_BT_LOGW_NODE(entry_node,
"Environment entry has unknown type: "
error:
g_free(left);
-
return ret;
}
}
if (!strcmp(left, "byte_order")) {
- enum bt_byte_order bo;
+ enum ctf_byte_order bo;
if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
_BT_LOGE_DUP_ATTR(node, "byte_order",
&node->u.ctf_expression.right,
struct ctf_node, siblings);
bo = byte_order_from_unary_expr(right_node);
- if (bo == BT_BYTE_ORDER_UNKNOWN) {
+ if (bo == -1) {
_BT_LOGE_NODE(node,
"Invalid `byte_order` attribute in trace (`trace` block): "
"expecting `le`, `be`, or `network`.");
ret = -EINVAL;
goto error;
- } else if (bo == BT_BYTE_ORDER_NATIVE) {
+ } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
_BT_LOGE_NODE(node,
"Invalid `byte_order` attribute in trace (`trace` block): "
"cannot be set to `native` here.");
goto error;
}
- ctx->trace_bo = bo;
- ret = bt_trace_set_native_byte_order(
- ctx->trace, bo);
- if (ret) {
- _BT_LOGE_NODE(node,
- "Cannot set trace's byte order: "
- "ret=%d", ret);
- goto error;
- }
+ ctx->ctf_tc->default_byte_order = bo;
}
g_free(left);
error:
g_free(left);
-
return ret;
}
static
int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_clock_class *clock, int *set)
+ struct bt_clock_class *clock, int *set, int64_t *offset_seconds,
+ uint64_t *offset_cycles)
{
int ret = 0;
char *left = NULL;
g_free(right);
_SET(set, _CLOCK_NAME_SET);
} else if (!strcmp(left, "uuid")) {
- unsigned char uuid[BABELTRACE_UUID_LEN];
+ uint8_t uuid[BABELTRACE_UUID_LEN];
if (_IS_SET(set, _CLOCK_UUID_SET)) {
_BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class");
g_free(right);
_SET(set, _CLOCK_DESCRIPTION_SET);
} else if (!strcmp(left, "freq")) {
- uint64_t freq = -1ULL;
+ uint64_t freq = UINT64_C(-1);
if (_IS_SET(set, _CLOCK_FREQ_SET)) {
_BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class");
goto error;
}
- if (freq == -1ULL || freq == 0) {
+ if (freq == UINT64_C(-1) || freq == 0) {
_BT_LOGE_NODE(entry_node,
"Invalid clock class frequency: freq=%" PRIu64,
freq);
_SET(set, _CLOCK_PRECISION_SET);
} else if (!strcmp(left, "offset_s")) {
- int64_t offset_s;
-
if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
_BT_LOGE_DUP_ATTR(entry_node, "offset_s",
"clock class");
}
ret = get_unary_signed(
- &entry_node->u.ctf_expression.right, &offset_s);
+ &entry_node->u.ctf_expression.right, offset_seconds);
if (ret) {
_BT_LOGE_NODE(entry_node,
"Unexpected unary expression for clock class's `offset_s` attribute.");
goto error;
}
- ret = bt_clock_class_set_offset_s(clock, offset_s);
- if (ret) {
- _BT_LOGE_NODE(entry_node,
- "Cannot set clock class's offset in seconds.");
- goto error;
- }
-
_SET(set, _CLOCK_OFFSET_S_SET);
} else if (!strcmp(left, "offset")) {
- int64_t offset;
-
if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
_BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
ret = -EPERM;
goto error;
}
- ret = get_unary_signed(
- &entry_node->u.ctf_expression.right, &offset);
+ ret = get_unary_unsigned(
+ &entry_node->u.ctf_expression.right, offset_cycles);
if (ret) {
_BT_LOGE_NODE(entry_node,
"Unexpected unary expression for clock class's `offset` attribute.");
goto error;
}
- ret = bt_clock_class_set_offset_cycles(clock, offset);
- if (ret) {
- _BT_LOGE_NODE(entry_node,
- "Cannot set clock class's offset in cycles.");
- goto error;
- }
-
_SET(set, _CLOCK_OFFSET_SET);
} else if (!strcmp(left, "absolute")) {
struct ctf_node *right;
g_free(left);
left = NULL;
-
return 0;
error:
g_free(left);
-
return ret;
}
-static
-int64_t cycles_from_ns(uint64_t frequency, int64_t ns)
+static inline
+uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
{
- int64_t cycles;
+ uint64_t cycles;
/* 1GHz */
- if (frequency == 1000000000ULL) {
+ if (frequency == UINT64_C(1000000000)) {
cycles = ns;
} else {
cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
}
static
-int apply_clock_class_offset(struct ctx *ctx, struct bt_clock_class *clock)
+void calibrate_clock_class_offsets(int64_t *offset_seconds,
+ uint64_t *offset_cycles, uint64_t freq)
+{
+ if (*offset_cycles >= freq) {
+ const uint64_t s_in_offset_cycles = *offset_cycles / freq;
+
+ *offset_seconds += (int64_t) s_in_offset_cycles;
+ *offset_cycles -= (s_in_offset_cycles * freq);
+ }
+}
+
+static
+void apply_clock_class_offset(struct ctx *ctx, struct bt_clock_class *clock)
{
int ret;
uint64_t freq;
- int64_t offset_cycles;
- int64_t offset_to_apply;
+ int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
+ uint64_t offset_ns_to_apply;
+ int64_t cur_offset_s;
+ uint64_t cur_offset_cycles;
- freq = bt_clock_class_get_frequency(clock);
- if (freq == -1ULL) {
- BT_LOGE_STR("Cannot get clock class's frequency.");
- ret = -1;
+ if (ctx->decoder_config.clock_class_offset_s == 0 &&
+ ctx->decoder_config.clock_class_offset_ns == 0) {
goto end;
}
- ret = bt_clock_class_get_offset_cycles(clock, &offset_cycles);
- if (ret) {
- BT_LOGE_STR("Cannot get clock class's offset in cycles.");
- ret = -1;
- goto end;
+ /* Transfer nanoseconds to seconds as much as possible */
+ if (ctx->decoder_config.clock_class_offset_ns < 0) {
+ const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
+ const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
+ const int64_t extra_s = -abs_extra_s;
+ const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
+ (extra_s * INT64_C(1000000000));
+
+ BT_ASSERT(offset_ns > 0);
+ offset_ns_to_apply = (uint64_t) offset_ns;
+ offset_s_to_apply += extra_s;
+ } else {
+ const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
+ INT64_C(1000000000);
+ const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
+ (extra_s * INT64_C(1000000000));
+
+ BT_ASSERT(offset_ns >= 0);
+ offset_ns_to_apply = (uint64_t) offset_ns;
+ offset_s_to_apply += extra_s;
}
- offset_to_apply =
- ctx->decoder_config.clock_class_offset_s * 1000000000LL +
- ctx->decoder_config.clock_class_offset_ns;
- offset_cycles += cycles_from_ns(freq, offset_to_apply);
- ret = bt_clock_class_set_offset_cycles(clock, offset_cycles);
+ freq = bt_clock_class_get_frequency(clock);
+ bt_clock_class_get_offset(clock, &cur_offset_s, &cur_offset_cycles);
+
+ /* Apply offsets */
+ cur_offset_s += offset_s_to_apply;
+ cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
+
+ /*
+ * Recalibrate offsets because the part in cycles can be greater
+ * than the frequency at this point.
+ */
+ calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
+
+ /* Set final offsets */
+ ret = bt_clock_class_set_offset(clock, cur_offset_s, cur_offset_cycles);
+ BT_ASSERT(ret == 0);
end:
- return ret;
+ return;
}
static
struct ctf_node *entry_node;
struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
const char *clock_class_name;
+ int64_t offset_seconds = 0;
+ uint64_t offset_cycles = 0;
+ uint64_t freq;
if (clock_node->visited) {
return 0;
clock_node->visited = TRUE;
/* CTF 1.8's default frequency for a clock class is 1 GHz */
- clock = bt_clock_class_create(NULL, 1000000000);
+ clock = bt_clock_class_create();
if (!clock) {
_BT_LOGE_NODE(clock_node,
"Cannot create default clock class.");
ret = -ENOMEM;
- goto error;
+ goto end;
+ }
+
+ /* CTF: not absolute by default */
+ ret = bt_clock_class_set_is_absolute(clock, BT_FALSE);
+ if (ret) {
+ _BT_LOGE_NODE(clock_node,
+ "Cannot set clock class's absolute flag.");
+ goto end;
}
bt_list_for_each_entry(entry_node, decl_list, siblings) {
- ret = visit_clock_decl_entry(ctx, entry_node, clock, &set);
+ ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
+ &offset_seconds, &offset_cycles);
if (ret) {
_BT_LOGE_NODE(entry_node,
"Cannot visit clock class's entry: ret=%d",
ret);
- goto error;
+ goto end;
}
}
_BT_LOGE_NODE(clock_node,
"Missing `name` attribute in clock class.");
ret = -EPERM;
- goto error;
+ goto end;
}
clock_class_name = bt_clock_class_get_name(clock);
* it's a condition to be able to sort notifications
* from different sources.
*/
- ret = bt_clock_class_set_is_absolute(clock, 1);
+ ret = bt_clock_class_set_is_absolute(clock, BT_TRUE);
if (ret) {
_BT_LOGE_NODE(clock_node,
"Cannot set clock class's absolute flag.");
- goto error;
+ goto end;
}
}
- ret = apply_clock_class_offset(ctx, clock);
- if (ret) {
- _BT_LOGE_NODE(clock_node,
- "Cannot apply clock class's custom offset.");
- goto error;
- }
-
- ret = bt_trace_add_clock_class(ctx->trace, clock);
- if (ret) {
- _BT_LOGE_NODE(clock_node,
- "Cannot add clock class to trace.");
- goto error;
- }
+ /*
+ * Adjust offsets so that the part in cycles is less than the
+ * frequency (move to the part in seconds).
+ */
+ freq = bt_clock_class_get_frequency(clock);
+ calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
+ BT_ASSERT(offset_cycles < bt_clock_class_get_frequency(clock));
+ ret = bt_clock_class_set_offset(clock, offset_seconds, offset_cycles);
+ BT_ASSERT(ret == 0);
+ apply_clock_class_offset(ctx, clock);
+ g_ptr_array_add(ctx->ctf_tc->clock_classes, bt_get(clock));
-error:
+end:
BT_PUT(clock);
-
return ret;
}
break;
case NODE_TYPE_SPECIFIER_LIST:
{
- _BT_FIELD_TYPE_INIT(decl);
+ struct ctf_field_type *decl = NULL;
/*
* Just add the type specifier to the root
goto end;
}
- BT_PUT(decl);
+ ctf_field_type_destroy(decl);
+ decl = NULL;
break;
}
default:
}
static
-int set_trace_name(struct ctx *ctx)
+int try_set_trace_class_name(struct ctx *ctx)
{
- GString *name;
+ GString *name = NULL;
int ret = 0;
- struct bt_value *value = NULL;
+ struct ctf_trace_class_env_entry *env_entry;
+
+ if (ctx->ctf_tc->name->len > 0) {
+ /* Already set */
+ goto end;
+ }
- BT_ASSERT(bt_trace_get_stream_class_count(ctx->trace) == 0);
name = g_string_new(NULL);
if (!name) {
BT_LOGE_STR("Failed to allocate a GString.");
* Check if we have a trace environment string value named `hostname`.
* If so, use it as the trace name's prefix.
*/
- value = bt_trace_get_environment_field_value_by_name(ctx->trace,
+ env_entry = ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc,
"hostname");
- if (value && bt_value_is_string(value)) {
- const char *hostname;
-
- ret = bt_value_string_get(value, &hostname);
- BT_ASSERT(ret == 0);
- g_string_append(name, hostname);
+ if (env_entry &&
+ env_entry->type == CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR) {
+ g_string_append(name, env_entry->value.str->str);
- if (ctx->trace_name_suffix) {
+ if (ctx->trace_class_name_suffix) {
g_string_append_c(name, G_DIR_SEPARATOR);
}
}
- if (ctx->trace_name_suffix) {
- g_string_append(name, ctx->trace_name_suffix);
- }
-
- ret = bt_trace_set_name(ctx->trace, name->str);
- if (ret) {
- BT_LOGE("Cannot set trace's name: name=\"%s\"", name->str);
- goto error;
+ if (ctx->trace_class_name_suffix) {
+ g_string_append(name, ctx->trace_class_name_suffix);
}
+ g_string_assign(ctx->ctf_tc->name, name->str);
goto end;
-error:
- ret = -1;
-
end:
- bt_put(value);
-
if (name) {
g_string_free(name, TRUE);
}
return ret;
}
-static
-int move_ctx_stream_classes_to_trace(struct ctx *ctx)
-{
- int ret = 0;
- GHashTableIter iter;
- gpointer key, stream_class;
-
- if (g_hash_table_size(ctx->stream_classes) > 0 &&
- bt_trace_get_stream_class_count(ctx->trace) == 0) {
- /*
- * We're about to add the first stream class to the
- * trace. This will freeze the trace, and after this
- * we cannot set the name anymore. At this point,
- * set the trace name.
- */
- ret = set_trace_name(ctx);
- if (ret) {
- BT_LOGE_STR("Cannot set trace's name.");
- goto end;
- }
- }
-
- g_hash_table_iter_init(&iter, ctx->stream_classes);
-
- while (g_hash_table_iter_next(&iter, &key, &stream_class)) {
- ret = bt_trace_add_stream_class(ctx->trace,
- stream_class);
- if (ret) {
- int64_t id = bt_stream_class_get_id(stream_class);
- BT_LOGE("Cannot add stream class to trace: id=%" PRId64,
- id);
- goto end;
- }
- }
-
- g_hash_table_remove_all(ctx->stream_classes);
-
-end:
- return ret;
-}
-
BT_HIDDEN
struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
const struct ctf_metadata_decoder_config *decoder_config,
const char *name)
{
- int ret;
struct ctx *ctx = NULL;
- struct bt_trace *trace;
-
- trace = bt_trace_create();
- if (!trace) {
- BT_LOGE_STR("Cannot create empty trace.");
- goto error;
- }
-
- /* Set packet header to NULL to override the default one */
- ret = bt_trace_set_packet_header_field_type(trace, NULL);
- if (ret) {
- BT_LOGE_STR("Cannot reset initial trace's packet header field type.");
- goto error;
- }
/* Create visitor's context */
- ctx = ctx_create(trace, decoder_config, name);
+ ctx = ctx_create(decoder_config, name);
if (!ctx) {
BT_LOGE_STR("Cannot create visitor's context.");
goto error;
}
- trace = NULL;
goto end;
error:
ctx = NULL;
end:
- bt_put(trace);
return (void *) ctx;
}
}
BT_HIDDEN
-struct bt_trace *ctf_visitor_generate_ir_get_trace(
+struct bt_trace *ctf_visitor_generate_ir_get_ir_trace(
struct ctf_visitor_generate_ir *visitor)
{
struct ctx *ctx = (void *) visitor;
return bt_get(ctx->trace);
}
+BT_HIDDEN
+struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
+ struct ctf_visitor_generate_ir *visitor)
+{
+ struct ctx *ctx = (void *) visitor;
+
+ BT_ASSERT(ctx);
+ BT_ASSERT(ctx->ctf_tc);
+ return ctx->ctf_tc;
+}
+
BT_HIDDEN
int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
struct ctf_node *node)
case NODE_ROOT:
{
struct ctf_node *iter;
- int got_trace_decl = FALSE;
+ bool got_trace_decl = false;
/*
* The first thing we need is the native byte order of
* have the native byte order yet, and we don't have any
* trace block yet, then fail with EINCOMPLETE.
*/
- if (ctx->trace_bo == BT_BYTE_ORDER_NATIVE) {
+ if (ctx->ctf_tc->default_byte_order == -1) {
bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
if (got_trace_decl) {
_BT_LOGE_NODE(node,
goto end;
}
- got_trace_decl = TRUE;
+ got_trace_decl = true;
}
if (!got_trace_decl) {
}
}
- BT_ASSERT(ctx->trace_bo == BT_BYTE_ORDER_LITTLE_ENDIAN ||
- ctx->trace_bo == BT_BYTE_ORDER_BIG_ENDIAN);
+ BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
+ ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
BT_ASSERT(ctx->current_scope &&
- ctx->current_scope->parent_scope == NULL);
+ ctx->current_scope->parent_scope == NULL);
/* Environment */
bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
goto end;
}
- /* Move decoded stream classes to trace, if any */
- ret = move_ctx_stream_classes_to_trace(ctx);
+ /* Update default clock classes */
+ ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Set trace's name, if not already done */
+ ret = try_set_trace_class_name(ctx);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Update trace class meanings */
+ ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Update text arrays and sequences */
+ ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Resolve sequence lengths and variant tags */
+ ret = ctf_trace_class_resolve_field_types(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Update "in IR" for field types */
+ ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Update saved value indexes */
+ ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
if (ret) {
- BT_LOGE("Cannot move stream classes to trace: ret=%d", ret);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Validate what we have so far */
+ ret = ctf_trace_class_validate(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Copy new CTF metadata -> new IR metadata */
+ ret = ctf_trace_class_translate(ctx->trace, ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
}
end:
/*
* Babeltrace - CTF notification iterator
*
- * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
- * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
+ * Copyright (c) 2015-2018 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2015-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
*/
struct bt_field *base;
- /* index of next field to set */
+ /* Index of next field to set */
size_t index;
};
STATE_AFTER_STREAM_PACKET_CONTEXT,
STATE_EMIT_NOTIF_NEW_STREAM,
STATE_EMIT_NOTIF_NEW_PACKET,
- STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN,
- STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
- STATE_AFTER_STREAM_EVENT_HEADER,
- STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN,
- STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
- STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
- STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
+ STATE_DSCOPE_EVENT_HEADER_BEGIN,
+ STATE_DSCOPE_EVENT_HEADER_CONTINUE,
+ STATE_AFTER_EVENT_HEADER,
+ STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN,
+ STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE,
+ STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN,
+ STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE,
STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
STATE_EMIT_NOTIF_EVENT,
STATE_SKIP_PACKET_PADDING,
};
-struct trace_field_path_cache {
- /*
- * Indexes of the stream_id and stream_instance_id field in the packet
- * header structure, -1 if unset.
- */
- int stream_id;
- int stream_instance_id;
-};
-
-struct stream_class_field_path_cache {
- /*
- * Indexes of the v and id fields in the stream event header structure,
- * -1 if unset.
- */
- int v;
- int id;
-
- /*
- * index of the timestamp_end, packet_size and content_size fields in
- * the stream packet context structure. Set to -1 if the fields were
- * not found.
- */
- int timestamp_end;
- int packet_size;
- int content_size;
-};
-
-struct field_cb_override {
- enum bt_btr_status (* func)(void *value,
- struct bt_field_type *type, void *data);
- void *data;
-};
-
-/* Clock value: clock class and raw value */
-struct clock_value {
- struct bt_clock_class *clock_class; /* Weak */
- uint64_t raw_value;
-};
-
/* CTF notification iterator */
struct bt_notif_iter {
/* Visit stack */
*/
struct bt_field *cur_dscope_field;
- /* Trace and classes (owned by this) */
+ /*
+ * True if we're done filling a string field from a text
+ * array/sequence payload.
+ */
+ bool done_filling_string;
+
+ /* Trace and classes */
struct {
- struct bt_trace *trace;
- struct bt_stream_class *stream_class;
- struct bt_event_class *event_class;
+ struct ctf_trace_class *tc;
+ struct ctf_stream_class *sc;
+ struct ctf_event_class *ec;
} meta;
/* Current packet header field wrapper (NULL if not created yet) */
/* Current packet (NULL if not created yet) */
struct bt_packet *packet;
- /* Previous packet availability */
- enum bt_packet_previous_packet_availability prev_packet_avail;
-
- /* Previous packet (NULL if not available) */
- struct bt_packet *prev_packet;
-
/* Current stream (NULL if not set yet) */
struct bt_stream *stream;
/* Current event notification (NULL if not created yet) */
struct bt_notification *event_notif;
- /*
- * Current `timestamp_end` field (to consider before switching
- * packets). If it's set, it's a field which is within
- * `dscopes.stream_packet_context` below, which is in `packet`
- * above.
- */
- struct bt_field *cur_timestamp_end;
-
- /* Database of current dynamic scopes (owned by this) */
+ /* Database of current dynamic scopes */
struct {
struct bt_field *trace_packet_header;
struct bt_field *stream_packet_context;
- struct bt_field *stream_event_header;
- struct bt_field *stream_event_context;
- struct bt_field *event_context;
+ struct bt_field *event_header;
+ struct bt_field *event_common_context;
+ struct bt_field *event_spec_context;
struct bt_field *event_payload;
} dscopes;
- /*
- * Special field overrides.
- *
- * Overrides are used to implement the behaviours of special fields such
- * as "timestamp_end" (which must be ignored until the end of the
- * packet), "id" (event id) which can be present multiple times and must
- * be updated multiple time.
- *
- * This should be used to implement the behaviour of integer fields
- * mapped to clocks and other "tagged" fields (in CTF 2).
- *
- * bt_field_type to struct field_cb_override
- */
- GHashTable *field_overrides;
-
/* Current state */
enum state state;
bool stream_begin_emitted;
/* Current packet size (bits) (-1 if unknown) */
- int64_t cur_packet_size;
+ int64_t cur_exp_packet_total_size;
/* Current content size (bits) (-1 if unknown) */
- int64_t cur_content_size;
+ int64_t cur_exp_packet_content_size;
- /*
- * Offset, in the underlying media, of the current packet's start
- * (-1 if unknown).
- */
- off_t cur_packet_offset;
+ /* Current stream class ID */
+ int64_t cur_stream_class_id;
- /* bt_clock_class to uint64_t. */
- GHashTable *clock_states;
+ /* Current event class ID */
+ int64_t cur_event_class_id;
- /*
- * Cache of the trace-constant field paths (event header type)
- * associated to the current trace.
- */
- struct trace_field_path_cache trace_field_path_cache;
+ /* Current data stream ID */
+ int64_t cur_data_stream_id;
/*
- * Field path cache associated with the current stream class.
- * Ownership of this structure belongs to the field_path_caches HT.
+ * Offset, in the underlying media, of the current packet's
+ * start (-1 if unknown).
*/
- struct stream_class_field_path_cache *cur_sc_field_path_cache;
+ off_t cur_packet_offset;
+
+ /* Default clock's current value */
+ uint64_t default_clock_val;
- /* bt_stream_class to struct stream_class_field_path_cache. */
- GHashTable *sc_field_path_caches;
+ /* End of packet snapshots */
+ struct {
+ uint64_t discarded_events;
+ uint64_t packets;
+ uint64_t beginning_clock;
+ uint64_t end_clock;
+ } snapshots;
+
+ /* Stored values (for sequence lengths, variant tags) */
+ GArray *stored_values;
};
static inline
return "STATE_EMIT_NOTIF_NEW_PACKET";
case STATE_EMIT_NOTIF_NEW_STREAM:
return "STATE_EMIT_NOTIF_NEW_STREAM";
- case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
- return "STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN";
- case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
- return "STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE";
- case STATE_AFTER_STREAM_EVENT_HEADER:
- return "STATE_AFTER_STREAM_EVENT_HEADER";
- case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
- return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN";
- case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
- return "STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE";
- case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
- return "STATE_DSCOPE_EVENT_CONTEXT_BEGIN";
- case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
- return "STATE_DSCOPE_EVENT_CONTEXT_CONTINUE";
+ case STATE_DSCOPE_EVENT_HEADER_BEGIN:
+ return "STATE_DSCOPE_EVENT_HEADER_BEGIN";
+ case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
+ return "STATE_DSCOPE_EVENT_HEADER_CONTINUE";
+ case STATE_AFTER_EVENT_HEADER:
+ return "STATE_AFTER_EVENT_HEADER";
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
+ return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN";
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
+ return "STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE";
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
+ return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN";
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
+ return "STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE";
case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
return "STATE_DSCOPE_EVENT_PAYLOAD_BEGIN";
case STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE:
static
int bt_notif_iter_switch_packet(struct bt_notif_iter *notit);
-static
-enum bt_btr_status btr_timestamp_end_cb(void *value,
- struct bt_field_type *type, void *data);
-
static
struct stack *stack_new(struct bt_notif_iter *notit)
{
}
BT_LOGD("Created stack: notit-addr=%p, stack-addr=%p", notit, stack);
- return stack;
+ goto end;
error:
g_free(stack);
- return NULL;
+ stack = NULL;
+
+end:
+ return stack;
}
static
}
static
-int stack_push(struct stack *stack, struct bt_field *base)
+void stack_push(struct stack *stack, struct bt_field *base)
{
struct stack_entry *entry;
entry->base = base;
entry->index = 0;
stack->size++;
- return 0;
}
static inline
enum bt_notif_iter_status notif_iter_status_from_m_status(
enum bt_notif_iter_medium_status m_status)
{
+ /* They are the same */
return (int) m_status;
}
* in the middle of a packet header, packet context, or
* event.
*/
- if (notit->cur_packet_size >= 0) {
- if (packet_at(notit) == notit->cur_packet_size) {
+ if (notit->cur_exp_packet_total_size >= 0) {
+ if (packet_at(notit) ==
+ notit->cur_exp_packet_total_size) {
goto end;
}
} else {
"packet-cur=%zu, last-eh-at=%zu",
bt_notif_iter_medium_status_string(m_status),
state_string(notit->state),
- notit->cur_packet_size,
+ notit->cur_exp_packet_total_size,
notit->buf.at, packet_at(notit),
notit->buf.last_eh_at);
m_status = BT_NOTIF_ITER_MEDIUM_STATUS_ERROR;
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- if (buf_available_bits(notit) == 0) {
+ if (unlikely(buf_available_bits(notit) == 0)) {
/*
* This _cannot_ return BT_NOTIF_ITER_STATUS_OK
* _and_ no bits.
return status;
}
-static inline
-void reset_clock_value(struct clock_value *cv)
-{
- BT_ASSERT(cv);
- cv->clock_class = NULL;
- cv->raw_value = UINT64_C(-1);
-}
-
static
enum bt_notif_iter_status read_dscope_begin_state(
struct bt_notif_iter *notit,
- struct bt_field_type *dscope_field_type,
+ struct ctf_field_type *dscope_ft,
enum state done_state, enum state continue_state,
struct bt_field *dscope_field)
{
notit->cur_dscope_field = dscope_field;
BT_LOGV("Starting BTR: notit-addr=%p, btr-addr=%p, ft-addr=%p",
- notit, notit->btr, dscope_field_type);
- consumed_bits = bt_btr_start(notit->btr, dscope_field_type,
+ notit, notit->btr, dscope_ft);
+ consumed_bits = bt_btr_start(notit->btr, dscope_ft,
notit->buf.addr, notit->buf.at, packet_at(notit),
notit->buf.sz, &btr_status);
BT_LOGV("BTR consumed bits: size=%zu", consumed_bits);
goto end;
}
-
consumed_bits = bt_btr_continue(notit->btr, notit->buf.addr,
notit->buf.sz, &btr_status);
BT_LOGV("BTR consumed bits: size=%zu", consumed_bits);
static
void release_event_dscopes(struct bt_notif_iter *notit)
{
- notit->dscopes.stream_event_header = NULL;
+ notit->dscopes.event_header = NULL;
if (notit->event_header_field) {
bt_event_header_field_release(notit->event_header_field);
notit->event_header_field = NULL;
}
- notit->dscopes.stream_event_context = NULL;
- notit->dscopes.event_context = NULL;
+ notit->dscopes.event_common_context = NULL;
+ notit->dscopes.event_spec_context = NULL;
notit->dscopes.event_payload = NULL;
}
enum bt_notif_iter_status read_packet_header_begin_state(
struct bt_notif_iter *notit)
{
- struct bt_field_type *packet_header_type = NULL;
+ struct ctf_field_type *packet_header_ft = NULL;
enum bt_notif_iter_status ret = BT_NOTIF_ITER_STATUS_OK;
if (bt_notif_iter_switch_packet(notit)) {
}
/* Packet header type is common to the whole trace. */
- packet_header_type = bt_trace_borrow_packet_header_field_type(
- notit->meta.trace);
- if (!packet_header_type) {
+ packet_header_ft = notit->meta.tc->packet_header_ft;
+ if (!packet_header_ft) {
notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
goto end;
}
- /*
- * Create free packet header field from trace. This field is
- * going to be moved to the packet once we create it. We cannot
- * create the packet now because:
- *
- * 1. A packet is created from a stream.
- * 2. A stream is created from a stream class.
- * 3. We need the packet header field's content to know the ID
- * of the stream class to select.
- */
BT_ASSERT(!notit->packet_header_field);
- notit->packet_header_field = bt_trace_create_packet_header_field(
- notit->meta.trace);
- if (!notit->packet_header_field) {
- BT_LOGE_STR("Cannot create packet header field wrapper from trace.");
- ret = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
+
+ if (packet_header_ft->in_ir) {
+ /*
+ * Create free packet header field from trace. This
+ * field is going to be moved to the packet once we
+ * create it. We cannot create the packet now because:
+ *
+ * 1. A packet is created from a stream.
+ * 2. A stream is created from a stream class.
+ * 3. We need the packet header field's content to know
+ * the ID of the stream class to select.
+ */
+ notit->packet_header_field = bt_packet_header_field_create(
+ notit->meta.tc->ir_tc);
+ if (!notit->packet_header_field) {
+ BT_LOGE_STR("Cannot create packet header field wrapper from trace.");
+ ret = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.trace_packet_header =
+ bt_packet_header_field_borrow_field(notit->packet_header_field);
+ BT_ASSERT(notit->dscopes.trace_packet_header);
}
- notit->dscopes.trace_packet_header =
- bt_packet_header_field_borrow_field(notit->packet_header_field);
- BT_ASSERT(notit->dscopes.trace_packet_header);
+ notit->cur_stream_class_id = -1;
+ notit->cur_event_class_id = -1;
+ notit->cur_data_stream_id = -1;
BT_LOGV("Decoding packet header field:"
"notit-addr=%p, trace-addr=%p, trace-name=\"%s\", ft-addr=%p",
- notit, notit->meta.trace,
- bt_trace_get_name(notit->meta.trace), packet_header_type);
- ret = read_dscope_begin_state(notit, packet_header_type,
+ notit, notit->meta.tc,
+ notit->meta.tc->name->str, packet_header_ft);
+ ret = read_dscope_begin_state(notit, packet_header_ft,
STATE_AFTER_TRACE_PACKET_HEADER,
STATE_DSCOPE_TRACE_PACKET_HEADER_CONTINUE,
notit->dscopes.trace_packet_header);
BT_LOGW("Cannot decode packet header field: "
"notit-addr=%p, trace-addr=%p, "
"trace-name=\"%s\", ft-addr=%p",
- notit, notit->meta.trace,
- bt_trace_get_name(notit->meta.trace),
- packet_header_type);
+ notit, notit->meta.tc,
+ notit->meta.tc->name->str,
+ packet_header_ft);
}
end:
struct bt_notif_iter *notit)
{
return read_dscope_continue_state(notit,
- STATE_AFTER_TRACE_PACKET_HEADER);
-}
-
-static
-struct stream_class_field_path_cache *
-create_stream_class_field_path_cache_entry(
- struct bt_notif_iter *notit,
- struct bt_stream_class *stream_class)
-{
- int v = -1;
- int id = -1;
- int timestamp_end = -1;
- int packet_size = -1;
- int content_size = -1;
- struct stream_class_field_path_cache *cache_entry = g_new0(
- struct stream_class_field_path_cache, 1);
- struct bt_field_type *event_header = NULL, *packet_context = NULL;
-
- if (!cache_entry) {
- BT_LOGE_STR("Failed to allocate one stream class field path cache.");
- goto end;
- }
-
- event_header = bt_stream_class_borrow_event_header_field_type(
- stream_class);
- if (event_header && bt_field_type_is_structure(event_header)) {
- int i, count;
-
- count = bt_field_type_structure_get_field_count(
- event_header);
- BT_ASSERT(count >= 0);
-
- for (i = 0; i < count; i++) {
- int ret;
- const char *name;
-
- ret = bt_field_type_structure_borrow_field_by_index(
- event_header, &name, NULL, i);
- if (ret) {
- BT_LOGE("Cannot get event header structure field type's field: "
- "notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "ft-addr=%p, index=%d",
- notit, stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_header, i);
- goto error;
- }
-
- if (v != -1 && id != -1) {
- break;
- }
-
- if (v == -1 && strcmp(name, "v") == 0) {
- v = i;
- } else if (id == -1 && !strcmp(name, "id")) {
- id = i;
- }
- }
- }
-
- packet_context = bt_stream_class_borrow_packet_context_field_type(
- stream_class);
- if (packet_context && bt_field_type_is_structure(packet_context)) {
- int i, count;
-
- count = bt_field_type_structure_get_field_count(
- packet_context);
- BT_ASSERT(count >= 0);
-
- for (i = 0; i < count; i++) {
- int ret;
- const char *name;
- struct bt_field_type *field_type;
-
- if (timestamp_end != -1 && packet_size != -1 &&
- content_size != -1) {
- break;
- }
-
- ret = bt_field_type_structure_borrow_field_by_index(
- packet_context, &name, &field_type, i);
- if (ret) {
- BT_LOGE("Cannot get packet context structure field type's field: "
- "notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "ft-addr=%p, index=%d",
- notit, stream_class,
- bt_stream_class_get_name(stream_class),
- bt_stream_class_get_id(stream_class),
- event_header, i);
- goto error;
- }
-
- if (timestamp_end == -1 &&
- strcmp(name, "timestamp_end") == 0) {
- struct field_cb_override *override = g_new0(
- struct field_cb_override, 1);
-
- if (!override) {
- goto error;
- }
-
- override->func = btr_timestamp_end_cb;
- override->data = notit;
- g_hash_table_insert(notit->field_overrides,
- field_type, override);
- timestamp_end = i;
- } else if (packet_size == -1 &&
- !strcmp(name, "packet_size")) {
- packet_size = i;
- } else if (content_size == -1 &&
- !strcmp(name, "content_size")) {
- content_size = i;
- }
- }
- }
-
- cache_entry->v = v;
- cache_entry->id = id;
- cache_entry->timestamp_end = timestamp_end;
- cache_entry->packet_size = packet_size;
- cache_entry->content_size = content_size;
-
-end:
- return cache_entry;
-
-error:
- g_free(cache_entry);
- cache_entry = NULL;
- goto end;
-}
-
-static
-struct stream_class_field_path_cache *get_stream_class_field_path_cache(
- struct bt_notif_iter *notit,
- struct bt_stream_class *stream_class)
-{
- bool cache_entry_found;
- struct stream_class_field_path_cache *cache_entry;
-
- cache_entry_found = g_hash_table_lookup_extended(
- notit->sc_field_path_caches,
- stream_class, NULL, (gpointer) &cache_entry);
- if (unlikely(!cache_entry_found)) {
- cache_entry = create_stream_class_field_path_cache_entry(notit,
- stream_class);
- g_hash_table_insert(notit->sc_field_path_caches,
- stream_class, (gpointer) cache_entry);
- }
-
- return cache_entry;
+ STATE_AFTER_TRACE_PACKET_HEADER);
}
static inline
-enum bt_notif_iter_status set_current_stream_class(
- struct bt_notif_iter *notit)
+enum bt_notif_iter_status set_current_stream_class(struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *packet_header_type = NULL;
- struct bt_field_type *stream_id_field_type = NULL;
- struct bt_stream_class *new_stream_class = NULL;
- uint64_t stream_id;
-
- /* Clear the current stream class field path cache. */
- notit->cur_sc_field_path_cache = NULL;
-
- /* Is there any "stream_id" field in the packet header? */
- packet_header_type = bt_trace_borrow_packet_header_field_type(
- notit->meta.trace);
- if (!packet_header_type) {
+ struct ctf_stream_class *new_stream_class = NULL;
+
+ if (notit->cur_stream_class_id == -1) {
/*
- * No packet header, therefore no `stream_id` field,
- * therefore only one stream class.
+ * No current stream class ID field, therefore only one
+ * stream class.
*/
- goto single_stream_class;
- }
-
- BT_ASSERT(bt_field_type_is_structure(packet_header_type));
-
- // TODO: optimalize!
- stream_id_field_type =
- bt_field_type_structure_borrow_field_type_by_name(
- packet_header_type, "stream_id");
- if (stream_id_field_type) {
- /* Find appropriate stream class using current stream ID */
- int ret;
- struct bt_field *stream_id_field = NULL;
-
- BT_ASSERT(notit->dscopes.trace_packet_header);
+ if (notit->meta.tc->stream_classes->len != 1) {
+ BT_LOGW("Need exactly one stream class since there's "
+ "no stream class ID field: "
+ "notit-addr=%p, trace-name=\"%s\"",
+ notit, notit->meta.tc->name->str);
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
- // TODO: optimalize!
- stream_id_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.trace_packet_header, "stream_id");
- BT_ASSERT(stream_id_field);
- ret = bt_field_integer_unsigned_get_value(
- stream_id_field, &stream_id);
- BT_ASSERT(!ret);
- } else {
-single_stream_class:
- /* Only one stream: pick the first stream class */
- BT_ASSERT(bt_trace_get_stream_class_count(
- notit->meta.trace) == 1);
- stream_id = 0;
+ new_stream_class = notit->meta.tc->stream_classes->pdata[0];
+ notit->cur_stream_class_id = new_stream_class->id;
+ goto end;
}
- BT_LOGV("Found stream class ID to use: notit-addr=%p, "
- "stream-class-id=%" PRIu64 ", "
- "trace-addr=%p, trace-name=\"%s\"",
- notit, stream_id, notit->meta.trace,
- bt_trace_get_name(notit->meta.trace));
-
- new_stream_class = bt_trace_borrow_stream_class_by_id(
- notit->meta.trace, stream_id);
+ new_stream_class = ctf_trace_class_borrow_stream_class_by_id(
+ notit->meta.tc, notit->cur_stream_class_id);
if (!new_stream_class) {
BT_LOGW("No stream class with ID of stream class ID to use in trace: "
"notit-addr=%p, stream-class-id=%" PRIu64 ", "
"trace-addr=%p, trace-name=\"%s\"",
- notit, stream_id, notit->meta.trace,
- bt_trace_get_name(notit->meta.trace));
+ notit, notit->cur_stream_class_id, notit->meta.tc,
+ notit->meta.tc->name->str);
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
- if (notit->meta.stream_class) {
- if (new_stream_class != notit->meta.stream_class) {
+ if (notit->meta.sc) {
+ if (new_stream_class != notit->meta.sc) {
BT_LOGW("Two packets refer to two different stream classes within the same packet sequence: "
"notit-addr=%p, prev-stream-class-addr=%p, "
- "prev-stream-class-name=\"%s\", "
"prev-stream-class-id=%" PRId64 ", "
"next-stream-class-addr=%p, "
- "next-stream-class-name=\"%s\", "
"next-stream-class-id=%" PRId64 ", "
"trace-addr=%p, trace-name=\"%s\"",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
new_stream_class,
- bt_stream_class_get_name(new_stream_class),
- bt_stream_class_get_id(new_stream_class),
- notit->meta.trace,
- bt_trace_get_name(notit->meta.trace));
+ new_stream_class->id,
+ notit->meta.tc,
+ notit->meta.tc->name->str);
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
} else {
- notit->meta.stream_class = new_stream_class;
+ notit->meta.sc = new_stream_class;
}
BT_LOGV("Set current stream class: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
-
- /*
- * Retrieve (or lazily create) the current stream class field path
- * cache.
- */
- notit->cur_sc_field_path_cache = get_stream_class_field_path_cache(
- notit, notit->meta.stream_class);
- if (!notit->cur_sc_field_path_cache) {
- BT_LOGW("Cannot retrieve stream class field path from cache: "
- "notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
- }
+ "stream-class-id=%" PRId64,
+ notit, notit->meta.sc, notit->meta.sc->id);
end:
return status;
}
-static inline
-uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit)
-{
- struct bt_field *stream_instance_id_field = NULL;
- uint64_t stream_instance_id = -1ULL;
- int ret;
-
- if (!notit->dscopes.trace_packet_header) {
- goto end;
- }
-
- stream_instance_id_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.trace_packet_header, "stream_instance_id");
- if (!stream_instance_id_field) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
- &stream_instance_id);
- if (ret) {
- stream_instance_id = -1ULL;
- goto end;
- }
-
-end:
- return stream_instance_id;
-}
-
static inline
enum bt_notif_iter_status set_current_stream(struct bt_notif_iter *notit)
{
struct bt_stream *stream = NULL;
BT_LOGV("Calling user function (get stream): notit-addr=%p, "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
+ "stream-class-addr=%p, stream-class-id=%" PRId64,
+ notit, notit->meta.sc,
+ notit->meta.sc->id);
stream = bt_get(notit->medium.medops.borrow_stream(
- notit->meta.stream_class, get_cur_stream_instance_id(notit),
+ notit->meta.sc->ir_sc, notit->cur_data_stream_id,
notit->medium.data));
BT_LOGV("User function returned: stream-addr=%p", stream);
if (!stream) {
- BT_LOGW_STR("User function failed to return a stream object for the given stream class.");
+ BT_LOGW_STR("User function failed to return a stream object "
+ "for the given stream class.");
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
if (notit->stream && stream != notit->stream) {
- BT_LOGW("User function returned a different stream than the previous one for the same sequence of packets.");
+ BT_LOGW("User function returned a different stream than the "
+ "previous one for the same sequence of packets.");
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
BT_LOGV("Creating packet from stream: "
"notit-addr=%p, stream-addr=%p, "
"stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
"stream-class-id=%" PRId64,
- notit, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
+ notit, notit->stream, notit->meta.sc,
+ notit->meta.sc->id);
/* Create packet */
BT_ASSERT(notit->stream);
- packet = bt_packet_create(notit->stream, notit->prev_packet_avail,
- notit->prev_packet);
+ packet = bt_packet_create(notit->stream);
if (!packet) {
BT_LOGE("Cannot create packet from stream: "
"notit-addr=%p, stream-addr=%p, "
"stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
"stream-class-id=%" PRId64,
- notit, notit->stream, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
+ notit, notit->stream, notit->meta.sc,
+ notit->meta.sc->id);
goto error;
}
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *packet_context_type;
+ struct ctf_field_type *packet_context_ft;
- BT_ASSERT(notit->meta.stream_class);
- packet_context_type = bt_stream_class_borrow_packet_context_field_type(
- notit->meta.stream_class);
- if (!packet_context_type) {
+ BT_ASSERT(notit->meta.sc);
+ packet_context_ft = notit->meta.sc->packet_context_ft;
+ if (!packet_context_ft) {
BT_LOGV("No packet packet context field type in stream class: continuing: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class));
+ "stream-class-id=%" PRId64,
+ notit, notit->meta.sc,
+ notit->meta.sc->id);
notit->state = STATE_AFTER_STREAM_PACKET_CONTEXT;
goto end;
}
- /*
- * Create free packet context field from stream class. This
- * field is going to be moved to the packet once we create it.
- * We cannot create the packet now because a packet is created
- * from a stream, and this API must be able to return the packet
- * header and context fields without creating a stream
- * (bt_notif_iter_get_packet_header_context_fields()).
- */
BT_ASSERT(!notit->packet_context_field);
- notit->packet_context_field =
- bt_stream_class_create_packet_context_field(
- notit->meta.stream_class);
- if (!notit->packet_context_field) {
- BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
+
+ if (packet_context_ft->in_ir) {
+ /*
+ * Create free packet context field from stream class.
+ * This field is going to be moved to the packet once we
+ * create it. We cannot create the packet now because a
+ * packet is created from a stream, and this API must be
+ * able to return the packet header and context fields
+ * without creating a stream
+ * (bt_notif_iter_borrow_packet_header_context_fields()).
+ */
+ notit->packet_context_field =
+ bt_packet_context_field_create(notit->meta.sc->ir_sc);
+ if (!notit->packet_context_field) {
+ BT_LOGE_STR("Cannot create packet context field wrapper from stream class.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.stream_packet_context =
+ bt_packet_context_field_borrow_field(notit->packet_context_field);
+ BT_ASSERT(notit->dscopes.stream_packet_context);
}
- notit->dscopes.stream_packet_context =
- bt_packet_context_field_borrow_field(notit->packet_context_field);
- BT_ASSERT(notit->dscopes.stream_packet_context);
BT_LOGV("Decoding packet context field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
- "ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- packet_context_type);
- status = read_dscope_begin_state(notit, packet_context_type,
+ "stream-class-id=%" PRId64 ", ft-addr=%p",
+ notit, notit->meta.sc,
+ notit->meta.sc->id, packet_context_ft);
+ status = read_dscope_begin_state(notit, packet_context_ft,
STATE_AFTER_STREAM_PACKET_CONTEXT,
STATE_DSCOPE_STREAM_PACKET_CONTEXT_CONTINUE,
notit->dscopes.stream_packet_context);
if (status < 0) {
BT_LOGW("Cannot decode packet context field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
"stream-class-id=%" PRId64 ", ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- packet_context_type);
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
+ packet_context_ft);
}
end:
STATE_AFTER_STREAM_PACKET_CONTEXT);
}
-static inline
-uint64_t get_field_raw_clock_value(struct bt_field *base_field,
- const char *field_name, struct bt_clock_class **user_cc)
-{
- struct bt_field *field;
- struct bt_field_type *ft;
- struct bt_clock_class *clock_class = NULL;
- uint64_t val = UINT64_C(-1);
- int ret;
-
- field = bt_field_structure_borrow_field_by_name(base_field, field_name);
- if (!field) {
- goto end;
- }
-
- ft = bt_field_borrow_type(field);
- BT_ASSERT(ft);
-
- if (!bt_field_type_is_integer(ft)) {
- goto end;
- }
-
- clock_class = bt_field_type_integer_borrow_mapped_clock_class(ft);
- if (!clock_class) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(field, &val);
- BT_ASSERT(ret == 0);
-
-end:
- *user_cc = clock_class;
- return val;
-}
-
static
enum bt_notif_iter_status set_current_packet_content_sizes(
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field *packet_size_field = NULL;
- struct bt_field *content_size_field = NULL;
- uint64_t content_size = -1ULL, packet_size = -1ULL;
- if (!notit->dscopes.stream_packet_context) {
- goto end;
- }
-
- packet_size_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.stream_packet_context, "packet_size");
- content_size_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.stream_packet_context, "content_size");
- if (packet_size_field) {
- int ret = bt_field_integer_unsigned_get_value(
- packet_size_field, &packet_size);
-
- BT_ASSERT(ret == 0);
- if (packet_size == 0) {
- BT_LOGW("Invalid packet size: packet context field indicates packet size is zero: "
- "notit-addr=%p, packet-context-field-addr=%p",
- notit, notit->dscopes.stream_packet_context);
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
- } else if ((packet_size % 8) != 0) {
- BT_LOGW("Invalid packet size: packet context field indicates packet size is not a multiple of 8: "
+ if (notit->cur_exp_packet_total_size == -1) {
+ if (notit->cur_exp_packet_content_size != -1) {
+ BT_LOGW("Content size is set, but packet size is not: "
"notit-addr=%p, packet-context-field-addr=%p, "
- "packet-size=%" PRIu64,
+ "packet-size=%" PRId64 ", content-size=%" PRId64,
notit, notit->dscopes.stream_packet_context,
- packet_size);
+ notit->cur_exp_packet_total_size,
+ notit->cur_exp_packet_content_size);
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
- }
-
- if (content_size_field) {
- int ret = bt_field_integer_unsigned_get_value(
- content_size_field, &content_size);
-
- BT_ASSERT(ret == 0);
} else {
- content_size = packet_size;
+ if (notit->cur_exp_packet_content_size == -1) {
+ notit->cur_exp_packet_content_size =
+ notit->cur_exp_packet_total_size;
+ }
}
- if (content_size > packet_size) {
- BT_LOGW("Invalid packet or content size: packet context field indicates content size is greater than packet size: "
+ if (notit->cur_exp_packet_content_size >
+ notit->cur_exp_packet_total_size) {
+ BT_LOGW("Invalid packet or content size: "
+ "content size is greater than packet size: "
"notit-addr=%p, packet-context-field-addr=%p, "
- "packet-size=%" PRIu64 ", content-size=%" PRIu64,
+ "packet-size=%" PRId64 ", content-size=%" PRId64,
notit, notit->dscopes.stream_packet_context,
- packet_size, content_size);
+ notit->cur_exp_packet_total_size,
+ notit->cur_exp_packet_content_size);
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
- if (packet_size != -1ULL) {
- notit->cur_packet_size = packet_size;
- } else {
- /*
- * Use the content size as packet size indicator if the
- * packet size field is missing. This means there is no
- * padding in this stream.
- */
- notit->cur_packet_size = content_size;
- }
- notit->cur_content_size = content_size;
BT_LOGV("Set current packet and content sizes: "
"notit-addr=%p, packet-size=%" PRIu64 ", content-size=%" PRIu64,
- notit, packet_size, content_size);
+ notit, notit->cur_exp_packet_total_size,
+ notit->cur_exp_packet_content_size);
end:
return status;
}
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *event_header_type = NULL;
+ struct ctf_field_type *event_header_ft = NULL;
/* Reset the position of the last event header */
notit->buf.last_eh_at = notit->buf.at;
+ notit->cur_event_class_id = -1;
/* Check if we have some content left */
- if (notit->cur_content_size >= 0) {
- if (packet_at(notit) == notit->cur_content_size) {
+ if (notit->cur_exp_packet_content_size >= 0) {
+ if (unlikely(packet_at(notit) ==
+ notit->cur_exp_packet_content_size)) {
/* No more events! */
BT_LOGV("Reached end of packet: notit-addr=%p, "
"cur=%zu", notit, packet_at(notit));
notit->state = STATE_EMIT_NOTIF_END_OF_PACKET;
goto end;
- } else if (packet_at(notit) > notit->cur_content_size) {
+ } else if (unlikely(packet_at(notit) >
+ notit->cur_exp_packet_content_size)) {
/* That's not supposed to happen */
BT_LOGV("Before decoding event header field: cursor is passed the packet's content: "
"notit-addr=%p, content-size=%" PRId64 ", "
- "cur=%zu", notit, notit->cur_content_size,
+ "cur=%zu", notit,
+ notit->cur_exp_packet_content_size,
packet_at(notit));
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
+ } else {
+ /*
+ * "Infinite" content: we're done when the medium has
+ * nothing else for us.
+ */
+ status = buf_ensure_available_bits(notit);
+ if (status != BT_NOTIF_ITER_STATUS_OK) {
+ /*
+ * If this function returns
+ * `BT_NOTIF_ITER_STATUS_EOF`:
+ *
+ * 1. bt_notif_iter_get_next_notification()
+ * emits a "packet end" notification. This
+ * resets the current packet. The state
+ * remains unchanged otherwise.
+ * 2. This function is called again. It returns
+ * `BT_NOTIF_ITER_STATUS_EOF` again.
+ * 3. bt_notif_iter_get_next_notification()
+ * emits a "stream end" notification because
+ * there's no current packet. It sets the
+ * current state to `STATE_DONE`.
+ */
+ goto end;
+ }
}
release_event_dscopes(notit);
- BT_ASSERT(notit->meta.stream_class);
- event_header_type = bt_stream_class_borrow_event_header_field_type(
- notit->meta.stream_class);
- if (!event_header_type) {
- notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
+ BT_ASSERT(notit->meta.sc);
+ event_header_ft = notit->meta.sc->event_header_ft;
+ if (!event_header_ft) {
+ notit->state = STATE_AFTER_EVENT_HEADER;
goto end;
}
- BT_ASSERT(!notit->event_header_field);
- notit->event_header_field = bt_stream_class_create_event_header_field(
- notit->meta.stream_class);
- if (!notit->event_header_field) {
- BT_LOGE_STR("Cannot create event header field wrapper from trace.");
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
+ if (event_header_ft->in_ir) {
+ BT_ASSERT(!notit->event_header_field);
+ notit->event_header_field = bt_event_header_field_create(
+ notit->meta.sc->ir_sc);
+ if (!notit->event_header_field) {
+ BT_LOGE_STR("Cannot create event header field wrapper from trace.");
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
+ }
+
+ notit->dscopes.event_header =
+ bt_event_header_field_borrow_field(notit->event_header_field);
+ BT_ASSERT(notit->dscopes.event_header);
}
- notit->dscopes.stream_event_header =
- bt_event_header_field_borrow_field(notit->event_header_field);
- BT_ASSERT(notit->dscopes.stream_event_header);
BT_LOGV("Decoding event header field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
+ "stream-class-id=%" PRId64 ", "
"ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- event_header_type);
- status = read_dscope_begin_state(notit, event_header_type,
- STATE_AFTER_STREAM_EVENT_HEADER,
- STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE,
- notit->dscopes.stream_event_header);
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
+ event_header_ft);
+ status = read_dscope_begin_state(notit, event_header_ft,
+ STATE_AFTER_EVENT_HEADER,
+ STATE_DSCOPE_EVENT_HEADER_CONTINUE,
+ notit->dscopes.event_header);
if (status < 0) {
BT_LOGW("Cannot decode event header field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
"stream-class-id=%" PRId64 ", ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- event_header_type);
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
+ event_header_ft);
}
end:
struct bt_notif_iter *notit)
{
return read_dscope_continue_state(notit,
- STATE_AFTER_STREAM_EVENT_HEADER);
+ STATE_AFTER_EVENT_HEADER);
}
static inline
enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit)
{
- /*
- * The assert() calls in this function are okay because it is
- * assumed here that all the metadata objects have been
- * validated for CTF correctness before decoding actual streams.
- */
-
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *event_header_type;
- struct bt_field_type *id_field_type = NULL;
- struct bt_field_type *v_field_type = NULL;
- uint64_t event_id = -1ULL;
- int ret;
- event_header_type = bt_stream_class_borrow_event_header_field_type(
- notit->meta.stream_class);
- if (!event_header_type) {
- /*
- * No event header, therefore no event class ID field,
- * therefore only one event class.
- */
- goto single_event_class;
- }
+ struct ctf_event_class *new_event_class = NULL;
- /* Is there any "id"/"v" field in the event header? */
- BT_ASSERT(bt_field_type_is_structure(event_header_type));
- id_field_type = bt_field_type_structure_borrow_field_type_by_name(
- event_header_type, "id");
- v_field_type = bt_field_type_structure_borrow_field_type_by_name(
- event_header_type, "v");
- BT_ASSERT(notit->dscopes.stream_event_header);
- if (v_field_type) {
+ if (notit->cur_event_class_id == -1) {
/*
- * _ _____ _____
- * | | |_ _|_ _| __ __ _
- * | | | | | || '_ \ / _` |
- * | |___| | | || | | | (_| | S P E C I A L
- * |_____|_| |_||_| |_|\__, | C A S E â„¢
- * |___/
+ * No current event class ID field, therefore only one
+ * event class.
*/
- struct bt_field *v_field = NULL;
- struct bt_field *v_struct_field = NULL;
- struct bt_field *v_struct_id_field = NULL;
-
- // TODO: optimalize!
- v_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.stream_event_header, "v");
- BT_ASSERT(v_field);
-
- v_struct_field =
- bt_field_variant_borrow_current_field(v_field);
- if (!v_struct_field) {
- goto end_v_field_type;
- }
-
- // TODO: optimalize!
- v_struct_id_field = bt_field_structure_borrow_field_by_name(
- v_struct_field, "id");
- if (!v_struct_id_field) {
- goto end_v_field_type;
- }
-
- if (bt_field_is_integer(v_struct_id_field)) {
- ret = bt_field_integer_unsigned_get_value(
- v_struct_id_field, &event_id);
- if (ret) {
- BT_LOGV("Cannot get value of unsigned integer field (`id`): continuing: "
- "notit=%p, field-addr=%p",
- notit, v_struct_id_field);
- event_id = -1ULL;
- }
- }
- }
-
-end_v_field_type:
- if (id_field_type && event_id == -1ULL) {
- /* Check "id" field */
- struct bt_field *id_field = NULL;
- int ret_get_value = 0;
-
- // TODO: optimalize!
- id_field = bt_field_structure_borrow_field_by_name(
- notit->dscopes.stream_event_header, "id");
- if (!id_field) {
- goto check_event_id;
+ if (notit->meta.sc->event_classes->len != 1) {
+ BT_LOGW("Need exactly one event class since there's "
+ "no event class ID field: "
+ "notit-addr=%p, trace-name=\"%s\"",
+ notit, notit->meta.tc->name->str);
+ status = BT_NOTIF_ITER_STATUS_ERROR;
+ goto end;
}
- ret_get_value = bt_field_integer_unsigned_get_value(
- id_field, &event_id);
- BT_ASSERT(ret_get_value == 0);
- }
-
-check_event_id:
- if (event_id == -1ULL) {
-single_event_class:
- /* Event ID not found: single event? */
- BT_ASSERT(bt_stream_class_get_event_class_count(
- notit->meta.stream_class) == 1);
- event_id = 0;
+ new_event_class = notit->meta.sc->event_classes->pdata[0];
+ notit->cur_event_class_id = new_event_class->id;
+ goto end;
}
- BT_LOGV("Found event class ID to use: notit-addr=%p, "
- "stream-class-addr=%p, stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "event-class-id=%" PRIu64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- event_id);
- notit->meta.event_class = bt_stream_class_borrow_event_class_by_id(
- notit->meta.stream_class, event_id);
- if (!notit->meta.event_class) {
+ new_event_class = ctf_stream_class_borrow_event_class_by_id(
+ notit->meta.sc, notit->cur_event_class_id);
+ if (!new_event_class) {
BT_LOGW("No event class with ID of event class ID to use in stream class: "
- "notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
- "stream-class-id=%" PRId64 ", "
- "event-class-id=%" PRIu64,
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- event_id);
+ "notit-addr=%p, stream-class-id=%" PRIu64 ", "
+ "event-class-id=%" PRIu64 ", "
+ "trace-addr=%p, trace-name=\"%s\"",
+ notit, notit->meta.sc->id, notit->cur_event_class_id,
+ notit->meta.tc, notit->meta.tc->name->str);
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
}
+ notit->meta.ec = new_event_class;
BT_LOGV("Set current event class: "
"notit-addr=%p, event-class-addr=%p, "
- "event-class-name=\"%s\", event-class-id=%" PRId64,
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class));
+ "event-class-id=%" PRId64 ", "
+ "event-class-name=\"%s\"",
+ notit, notit->meta.ec, notit->meta.ec->id,
+ notit->meta.ec->name->str);
end:
return status;
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
struct bt_notification *notif = NULL;
- BT_ASSERT(notit->meta.event_class);
+ BT_ASSERT(notit->meta.ec);
BT_ASSERT(notit->packet);
BT_LOGV("Creating event notification from event class and packet: "
"notit-addr=%p, ec-addr=%p, ec-name=\"%s\", packet-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
notit->packet);
BT_ASSERT(notit->notif_iter);
notif = bt_notification_event_create(notit->notif_iter,
- notit->meta.event_class, notit->packet);
+ notit->meta.ec->ir_ec, notit->packet);
if (!notif) {
BT_LOGE("Cannot create event notification: "
"notit-addr=%p, ec-addr=%p, ec-name=\"%s\", "
"packet-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
notit->packet);
goto error;
}
BT_ASSERT(notit->event);
ret = bt_event_move_header(notit->event,
notit->event_header_field);
-
if (ret) {
status = BT_NOTIF_ITER_STATUS_ERROR;
goto end;
notit->event_header_field = NULL;
/*
- * At this point notit->dscopes.stream_event_header has
+ * At this point notit->dscopes.event_header has
* the same value as the event header field within
* notit->event.
*/
- BT_ASSERT(bt_event_borrow_header(notit->event) ==
- notit->dscopes.stream_event_header);
+ BT_ASSERT(bt_event_borrow_header_field(notit->event) ==
+ notit->dscopes.event_header);
}
- notit->state = STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN;
+ notit->state = STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN;
end:
return status;
}
static
-enum bt_notif_iter_status read_stream_event_context_begin_state(
+enum bt_notif_iter_status read_event_common_context_begin_state(
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *stream_event_context_type;
+ struct ctf_field_type *event_common_context_ft;
- stream_event_context_type =
- bt_stream_class_borrow_event_context_field_type(
- notit->meta.stream_class);
- if (!stream_event_context_type) {
- notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
+ event_common_context_ft = notit->meta.sc->event_common_context_ft;
+ if (!event_common_context_ft) {
+ notit->state = STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN;
goto end;
}
- BT_ASSERT(!notit->dscopes.stream_event_context);
- notit->dscopes.stream_event_context =
- bt_event_borrow_stream_event_context(notit->event);
- BT_ASSERT(notit->dscopes.stream_event_context);
- BT_LOGV("Decoding stream event context field: "
+ if (event_common_context_ft->in_ir) {
+ BT_ASSERT(!notit->dscopes.event_common_context);
+ notit->dscopes.event_common_context =
+ bt_event_borrow_common_context_field(notit->event);
+ BT_ASSERT(notit->dscopes.event_common_context);
+ }
+
+ BT_LOGV("Decoding event common context field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", stream-class-id=%" PRId64 ", "
+ "stream-class-id=%" PRId64 ", "
"ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- stream_event_context_type);
- status = read_dscope_begin_state(notit, stream_event_context_type,
- STATE_DSCOPE_EVENT_CONTEXT_BEGIN,
- STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE,
- notit->dscopes.stream_event_context);
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
+ event_common_context_ft);
+ status = read_dscope_begin_state(notit, event_common_context_ft,
+ STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN,
+ STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE,
+ notit->dscopes.event_common_context);
if (status < 0) {
- BT_LOGW("Cannot decode stream event context field: "
+ BT_LOGW("Cannot decode event common context field: "
"notit-addr=%p, stream-class-addr=%p, "
- "stream-class-name=\"%s\", "
"stream-class-id=%" PRId64 ", ft-addr=%p",
- notit, notit->meta.stream_class,
- bt_stream_class_get_name(notit->meta.stream_class),
- bt_stream_class_get_id(notit->meta.stream_class),
- stream_event_context_type);
+ notit, notit->meta.sc,
+ notit->meta.sc->id,
+ event_common_context_ft);
}
end:
}
static
-enum bt_notif_iter_status read_stream_event_context_continue_state(
+enum bt_notif_iter_status read_event_common_context_continue_state(
struct bt_notif_iter *notit)
{
return read_dscope_continue_state(notit,
- STATE_DSCOPE_EVENT_CONTEXT_BEGIN);
+ STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN);
}
static
-enum bt_notif_iter_status read_event_context_begin_state(
+enum bt_notif_iter_status read_event_spec_context_begin_state(
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *event_context_type;
+ struct ctf_field_type *event_spec_context_ft;
- event_context_type = bt_event_class_borrow_context_field_type(
- notit->meta.event_class);
- if (!event_context_type) {
+ event_spec_context_ft = notit->meta.ec->spec_context_ft;
+ if (!event_spec_context_ft) {
notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
goto end;
}
- BT_ASSERT(!notit->dscopes.event_context);
- notit->dscopes.event_context = bt_event_borrow_context(notit->event);
- BT_ASSERT(notit->dscopes.event_context);
- BT_LOGV("Decoding event context field: "
+ if (event_spec_context_ft->in_ir) {
+ BT_ASSERT(!notit->dscopes.event_spec_context);
+ notit->dscopes.event_spec_context = bt_event_borrow_specific_context_field(
+ notit->event);
+ BT_ASSERT(notit->dscopes.event_spec_context);
+ }
+
+ BT_LOGV("Decoding event specific context field: "
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
"ft-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- event_context_type);
- status = read_dscope_begin_state(notit, event_context_type,
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
+ notit->meta.ec->id,
+ event_spec_context_ft);
+ status = read_dscope_begin_state(notit, event_spec_context_ft,
STATE_DSCOPE_EVENT_PAYLOAD_BEGIN,
- STATE_DSCOPE_EVENT_CONTEXT_CONTINUE,
- notit->dscopes.event_context);
+ STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE,
+ notit->dscopes.event_spec_context);
if (status < 0) {
- BT_LOGW("Cannot decode event context field: "
+ BT_LOGW("Cannot decode event specific context field: "
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", "
"event-class-id=%" PRId64 ", ft-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- event_context_type);
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
+ notit->meta.ec->id,
+ event_spec_context_ft);
}
end:
}
static
-enum bt_notif_iter_status read_event_context_continue_state(
+enum bt_notif_iter_status read_event_spec_context_continue_state(
struct bt_notif_iter *notit)
{
return read_dscope_continue_state(notit,
struct bt_notif_iter *notit)
{
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
- struct bt_field_type *event_payload_type;
+ struct ctf_field_type *event_payload_ft;
- event_payload_type = bt_event_class_borrow_payload_field_type(
- notit->meta.event_class);
- if (!event_payload_type) {
+ event_payload_ft = notit->meta.ec->payload_ft;
+ if (!event_payload_ft) {
notit->state = STATE_EMIT_NOTIF_EVENT;
goto end;
}
- BT_ASSERT(!notit->dscopes.event_payload);
- notit->dscopes.event_payload = bt_event_borrow_payload(notit->event);
- BT_ASSERT(notit->dscopes.event_payload);
+ if (event_payload_ft->in_ir) {
+ BT_ASSERT(!notit->dscopes.event_payload);
+ notit->dscopes.event_payload = bt_event_borrow_payload_field(
+ notit->event);
+ BT_ASSERT(notit->dscopes.event_payload);
+ }
+
BT_LOGV("Decoding event payload field: "
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", event-class-id=%" PRId64 ", "
"ft-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- event_payload_type);
- status = read_dscope_begin_state(notit, event_payload_type,
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
+ notit->meta.ec->id,
+ event_payload_ft);
+ status = read_dscope_begin_state(notit, event_payload_ft,
STATE_EMIT_NOTIF_EVENT,
STATE_DSCOPE_EVENT_PAYLOAD_CONTINUE,
notit->dscopes.event_payload);
"notit-addr=%p, event-class-addr=%p, "
"event-class-name=\"%s\", "
"event-class-id=%" PRId64 ", ft-addr=%p",
- notit, notit->meta.event_class,
- bt_event_class_get_name(notit->meta.event_class),
- bt_event_class_get_id(notit->meta.event_class),
- event_payload_type);
+ notit, notit->meta.ec,
+ notit->meta.ec->name->str,
+ notit->meta.ec->id,
+ event_payload_ft);
}
end:
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
size_t bits_to_skip;
- BT_ASSERT(notit->cur_packet_size > 0);
- bits_to_skip = notit->cur_packet_size - packet_at(notit);
+ BT_ASSERT(notit->cur_exp_packet_total_size > 0);
+ bits_to_skip = notit->cur_exp_packet_total_size - packet_at(notit);
if (bits_to_skip == 0) {
notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
goto end;
BT_LOGV("Skipping %zu bits of padding: notit-addr=%p, size=%zu",
bits_to_consume, notit, bits_to_consume);
buf_consume_bits(notit, bits_to_consume);
- bits_to_skip = notit->cur_packet_size - packet_at(notit);
+ bits_to_skip = notit->cur_exp_packet_total_size -
+ packet_at(notit);
if (bits_to_skip == 0) {
notit->state = STATE_DSCOPE_TRACE_PACKET_HEADER_BEGIN;
goto end;
notit->state = STATE_EMIT_NOTIF_NEW_PACKET;
break;
case STATE_EMIT_NOTIF_NEW_PACKET:
- notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
+ notit->state = STATE_DSCOPE_EVENT_HEADER_BEGIN;
break;
- case STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN:
+ case STATE_DSCOPE_EVENT_HEADER_BEGIN:
status = read_event_header_begin_state(notit);
break;
- case STATE_DSCOPE_STREAM_EVENT_HEADER_CONTINUE:
+ case STATE_DSCOPE_EVENT_HEADER_CONTINUE:
status = read_event_header_continue_state(notit);
break;
- case STATE_AFTER_STREAM_EVENT_HEADER:
+ case STATE_AFTER_EVENT_HEADER:
status = after_event_header_state(notit);
break;
- case STATE_DSCOPE_STREAM_EVENT_CONTEXT_BEGIN:
- status = read_stream_event_context_begin_state(notit);
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_BEGIN:
+ status = read_event_common_context_begin_state(notit);
break;
- case STATE_DSCOPE_STREAM_EVENT_CONTEXT_CONTINUE:
- status = read_stream_event_context_continue_state(notit);
+ case STATE_DSCOPE_EVENT_COMMON_CONTEXT_CONTINUE:
+ status = read_event_common_context_continue_state(notit);
break;
- case STATE_DSCOPE_EVENT_CONTEXT_BEGIN:
- status = read_event_context_begin_state(notit);
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_BEGIN:
+ status = read_event_spec_context_begin_state(notit);
break;
- case STATE_DSCOPE_EVENT_CONTEXT_CONTINUE:
- status = read_event_context_continue_state(notit);
+ case STATE_DSCOPE_EVENT_SPEC_CONTEXT_CONTINUE:
+ status = read_event_spec_context_continue_state(notit);
break;
case STATE_DSCOPE_EVENT_PAYLOAD_BEGIN:
status = read_event_payload_begin_state(notit);
status = read_event_payload_continue_state(notit);
break;
case STATE_EMIT_NOTIF_EVENT:
- notit->state = STATE_DSCOPE_STREAM_EVENT_HEADER_BEGIN;
+ notit->state = STATE_DSCOPE_EVENT_HEADER_BEGIN;
break;
case STATE_SKIP_PACKET_PADDING:
status = skip_packet_padding_state(notit);
BT_ASSERT(notit);
BT_LOGD("Resetting notification iterator: addr=%p", notit);
stack_clear(notit->stack);
- notit->meta.stream_class = NULL;
- notit->meta.event_class = NULL;
+ notit->meta.sc = NULL;
+ notit->meta.ec = NULL;
BT_PUT(notit->packet);
- notit->prev_packet_avail = BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE;
- BT_PUT(notit->prev_packet);
BT_PUT(notit->stream);
BT_PUT(notit->event_notif);
release_all_dscopes(notit);
notit->buf.last_eh_at = SIZE_MAX;
notit->buf.packet_offset = 0;
notit->state = STATE_INIT;
- notit->cur_content_size = -1;
- notit->cur_packet_size = -1;
+ notit->cur_exp_packet_content_size = -1;
+ notit->cur_exp_packet_total_size = -1;
notit->cur_packet_offset = -1;
+ notit->cur_stream_class_id = -1;
+ notit->cur_event_class_id = -1;
+ notit->cur_data_stream_id = -1;
notit->stream_begin_emitted = false;
- notit->cur_timestamp_end = NULL;
}
static
*/
BT_ASSERT(notit);
- if (notit->cur_packet_size != -1) {
- notit->cur_packet_offset += notit->cur_packet_size;
+ if (notit->cur_exp_packet_total_size != -1) {
+ notit->cur_packet_offset += notit->cur_exp_packet_total_size;
}
BT_LOGV("Switching packet: notit-addr=%p, cur=%zu, "
"packet-offset=%" PRId64, notit, notit->buf.at,
notit->cur_packet_offset);
stack_clear(notit->stack);
- notit->meta.event_class = NULL;
+ notit->meta.ec = NULL;
BT_PUT(notit->packet);
BT_PUT(notit->event_notif);
- notit->cur_timestamp_end = NULL;
release_all_dscopes(notit);
notit->cur_dscope_field = NULL;
notit->buf.addr, notit->buf.sz);
}
- notit->cur_content_size = -1;
- notit->cur_packet_size = -1;
- notit->cur_sc_field_path_cache = NULL;
+ notit->cur_exp_packet_content_size = -1;
+ notit->cur_exp_packet_total_size = -1;
+ notit->cur_stream_class_id = -1;
+ notit->cur_event_class_id = -1;
+ notit->cur_data_stream_id = -1;
+ notit->snapshots.discarded_events = UINT64_C(-1);
+ notit->snapshots.packets = UINT64_C(-1);
+ notit->snapshots.beginning_clock = UINT64_C(-1);
+ notit->snapshots.end_clock = UINT64_C(-1);
end:
return ret;
{
struct bt_field *next_field = NULL;
struct bt_field *base_field;
- struct bt_field_type *base_type;
+ struct bt_field_type *base_ft;
size_t index;
BT_ASSERT(!stack_empty(notit->stack));
index = stack_top(notit->stack)->index;
base_field = stack_top(notit->stack)->base;
BT_ASSERT(base_field);
- base_type = bt_field_borrow_type(base_field);
- BT_ASSERT(base_type);
+ base_ft = bt_field_borrow_type(base_field);
+ BT_ASSERT(base_ft);
- switch (bt_field_type_get_type_id(base_type)) {
- case BT_FIELD_TYPE_ID_STRUCT:
+ switch (bt_field_type_get_type_id(base_ft)) {
+ case BT_FIELD_TYPE_ID_STRUCTURE:
{
- next_field = bt_field_structure_borrow_field_by_index(
+ BT_ASSERT(index <
+ bt_field_type_structure_get_member_count(
+ bt_field_borrow_type(base_field)));
+ next_field = bt_field_structure_borrow_member_field_by_index(
base_field, index);
break;
}
- case BT_FIELD_TYPE_ID_ARRAY:
- next_field = bt_field_array_borrow_field(base_field, index);
- break;
- case BT_FIELD_TYPE_ID_SEQUENCE:
- next_field = bt_field_sequence_borrow_field(base_field, index);
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
+ BT_ASSERT(index < bt_field_array_get_length(base_field));
+ next_field = bt_field_array_borrow_element_field_by_index(
+ base_field, index);
break;
case BT_FIELD_TYPE_ID_VARIANT:
- next_field = bt_field_variant_borrow_current_field(base_field);
+ BT_ASSERT(index == 0);
+ next_field = bt_field_variant_borrow_selected_option_field(
+ base_field);
break;
default:
- BT_LOGF("Unknown base field type ID: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s",
- notit, base_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(base_type)));
abort();
}
+ BT_ASSERT(next_field);
return next_field;
}
static
-void update_clock_state(uint64_t *state, struct bt_field *value_field,
- struct bt_field_type *value_type)
+void update_default_clock(struct bt_notif_iter *notit, uint64_t new_val,
+ uint64_t new_val_size)
{
- uint64_t requested_new_value;
- uint64_t requested_new_value_mask;
+ uint64_t new_val_mask;
uint64_t cur_value_masked;
- int requested_new_value_size;
- int ret;
- BT_ASSERT(value_type);
- BT_ASSERT(bt_field_type_is_integer(value_type));
- requested_new_value_size =
- bt_field_type_integer_get_size(value_type);
- BT_ASSERT(requested_new_value_size > 0);
- ret = bt_field_integer_unsigned_get_value(value_field,
- &requested_new_value);
- BT_ASSERT(!ret);
+ BT_ASSERT(new_val_size > 0);
/*
* Special case for a 64-bit new value, which is the limit
* of a clock value as of this version: overwrite the
* current value directly.
*/
- if (requested_new_value_size == 64) {
- *state = requested_new_value;
+ if (new_val_size == 64) {
+ notit->default_clock_val = new_val;
goto end;
}
- requested_new_value_mask = (1ULL << requested_new_value_size) - 1;
- cur_value_masked = *state & requested_new_value_mask;
+ new_val_mask = (1ULL << new_val_size) - 1;
+ cur_value_masked = notit->default_clock_val & new_val_mask;
- if (requested_new_value < cur_value_masked) {
+ if (new_val < cur_value_masked) {
/*
* It looks like a wrap happened on the number of bits
* of the requested new value. Assume that the clock
* value wrapped only one time.
*/
- *state += requested_new_value_mask + 1;
+ notit->default_clock_val += new_val_mask + 1;
}
/* Clear the low bits of the current clock value. */
- *state &= ~requested_new_value_mask;
+ notit->default_clock_val &= ~new_val_mask;
/* Set the low bits of the current clock value. */
- *state |= requested_new_value;
+ notit->default_clock_val |= new_val;
end:
- BT_LOGV("Updated clock's value from integer field's value: "
- "value=%" PRIu64, *state);
+ BT_LOGV("Updated default clock's value from integer field's value: "
+ "value=%" PRIu64, notit->default_clock_val);
}
static
-enum bt_btr_status update_clock(struct bt_notif_iter *notit,
- struct bt_field *int_field)
+enum bt_btr_status btr_unsigned_int_cb(uint64_t value,
+ struct ctf_field_type *ft, void *data)
{
- gboolean clock_class_found;
- uint64_t *clock_state = NULL;
- struct bt_field_type *int_field_type = NULL;
- enum bt_btr_status ret = BT_BTR_STATUS_OK;
- struct bt_clock_class *clock_class = NULL;
+ struct bt_notif_iter *notit = data;
+ enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct bt_field *field = NULL;
+ struct ctf_field_type_int *int_ft = (void *) ft;
- int_field_type = bt_field_borrow_type(int_field);
- BT_ASSERT(int_field_type);
-
- if (bt_field_type_is_enumeration(int_field_type)) {
- int_field_type =
- bt_field_type_enumeration_borrow_container_field_type(
- int_field_type);
- }
+ BT_LOGV("Unsigned integer function called from BTR: "
+ "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
+ "ft-id=%d, ft-in-ir=%d, value=%" PRIu64,
+ notit, notit->btr, ft, ft->id, ft->in_ir, value);
- clock_class = bt_field_type_integer_borrow_mapped_clock_class(
- int_field_type);
- if (likely(!clock_class)) {
- goto end;
+ if (likely(int_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE)) {
+ goto update_def_clock;
}
- clock_class_found = g_hash_table_lookup_extended(notit->clock_states,
- clock_class, NULL, (gpointer) &clock_state);
- if (!clock_class_found) {
- clock_state = g_new0(uint64_t, 1);
- if (!clock_state) {
- BT_LOGE_STR("Failed to allocate a uint64_t.");
- ret = BT_BTR_STATUS_ENOMEM;
+ switch (int_ft->meaning) {
+ case CTF_FIELD_TYPE_MEANING_EVENT_CLASS_ID:
+ notit->cur_event_class_id = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_DATA_STREAM_ID:
+ notit->cur_data_stream_id = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_PACKET_BEGINNING_TIME:
+ notit->snapshots.beginning_clock = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_PACKET_END_TIME:
+ notit->snapshots.end_clock = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_STREAM_CLASS_ID:
+ notit->cur_stream_class_id = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_MAGIC:
+ if (value != 0xc1fc1fc1) {
+ BT_LOGW("Invalid CTF magic number: notit-addr=%p, "
+ "magic=%" PRIx64, notit, value);
+ status = BT_BTR_STATUS_ERROR;
goto end;
}
- g_hash_table_insert(notit->clock_states, clock_class,
- clock_state);
+ break;
+ case CTF_FIELD_TYPE_MEANING_PACKET_COUNTER_SNAPSHOT:
+ notit->snapshots.packets = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_DISC_EV_REC_COUNTER_SNAPSHOT:
+ notit->snapshots.discarded_events = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_EXP_PACKET_TOTAL_SIZE:
+ notit->cur_exp_packet_total_size = value;
+ break;
+ case CTF_FIELD_TYPE_MEANING_EXP_PACKET_CONTENT_SIZE:
+ notit->cur_exp_packet_content_size = value;
+ break;
+ default:
+ abort();
}
- /* Update the clock's state. */
- BT_LOGV("Updating notification iterator's clock's value from integer field: "
- "notit-addr=%p, clock-class-addr=%p, "
- "clock-class-name=\"%s\", value=%" PRIu64,
- notit, clock_class,
- bt_clock_class_get_name(clock_class), *clock_state);
- update_clock_state(clock_state, int_field, int_field_type);
-
-end:
- return ret;
-}
+update_def_clock:
+ if (unlikely(int_ft->mapped_clock_class)) {
+ update_default_clock(notit, value, int_ft->base.size);
+ }
-static
-enum bt_btr_status btr_unsigned_int_common(uint64_t value,
- struct bt_field_type *type, void *data,
- struct bt_field **out_field)
-{
- enum bt_btr_status status = BT_BTR_STATUS_OK;
- struct bt_field *field = NULL;
- struct bt_notif_iter *notit = data;
- int ret;
+ if (unlikely(int_ft->storing_index >= 0)) {
+ g_array_index(notit->stored_values, uint64_t,
+ (uint64_t) int_ft->storing_index) = value;
+ }
- BT_LOGV("Common unsigned integer function called from BTR: "
- "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s, value=%" PRIu64,
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
- value);
- field = borrow_next_field(notit);
- if (!field) {
- BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
- status = BT_BTR_STATUS_ERROR;
+ if (unlikely(!ft->in_ir)) {
goto end;
}
- BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
- ret = bt_field_integer_unsigned_set_value(field, value);
- BT_ASSERT(ret == 0);
+ field = borrow_next_field(notit);
+ BT_ASSERT(field);
+ BT_ASSERT(bt_field_borrow_type(field) == ft->ir_ft);
+ BT_ASSERT(bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER ||
+ bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION);
+ bt_field_unsigned_integer_set_value(field, value);
stack_top(notit->stack)->index++;
- *out_field = field;
end:
return status;
}
static
-enum bt_btr_status btr_timestamp_end_cb(void *value,
- struct bt_field_type *type, void *data)
+enum bt_btr_status btr_unsigned_int_char_cb(uint64_t value,
+ struct ctf_field_type *ft, void *data)
{
- enum bt_btr_status status;
- struct bt_field *field = NULL;
+ int ret;
struct bt_notif_iter *notit = data;
- uint64_t uvalue = *((uint64_t *) value);
+ enum bt_btr_status status = BT_BTR_STATUS_OK;
+ struct bt_field *string_field = NULL;
+ struct ctf_field_type_int *int_ft = (void *) ft;
+ char str[2] = {'\0', '\0'};
- BT_LOGV("`timestamp_end` unsigned integer function called from BTR: "
+ BT_LOGV("Unsigned integer character function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
-
- status = btr_unsigned_int_common(uvalue, type, data, &field);
+ "ft-id=%d, ft-in-ir=%d, value=%" PRIu64,
+ notit, notit->btr, ft, ft->id, ft->in_ir, value);
+ BT_ASSERT(int_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE);
+ BT_ASSERT(!int_ft->mapped_clock_class);
+ BT_ASSERT(int_ft->storing_index < 0);
- /* Set as the current packet's end timestamp field */
- notit->cur_timestamp_end = field;
- return status;
-}
-
-static
-enum bt_btr_status btr_unsigned_int_cb(uint64_t value,
- struct bt_field_type *type, void *data)
-{
- struct bt_notif_iter *notit = data;
- enum bt_btr_status status = BT_BTR_STATUS_OK;
- struct bt_field *field = NULL;
- struct field_cb_override *override;
+ if (unlikely(!ft->in_ir)) {
+ goto end;
+ }
- BT_LOGV("Unsigned integer function called from BTR: "
- "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s, value=%" PRIu64,
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
- value);
- override = g_hash_table_lookup(notit->field_overrides, type);
- if (unlikely(override)) {
- /* Override function logs errors */
- status = override->func(&value, type, override->data);
+ if (notit->done_filling_string) {
goto end;
}
- status = btr_unsigned_int_common(value, type, data, &field);
- if (status != BT_BTR_STATUS_OK) {
- /* btr_unsigned_int_common() logs errors */
+ if (value == 0) {
+ notit->done_filling_string = true;
goto end;
}
- status = update_clock(notit, field);
+ string_field = stack_top(notit->stack)->base;
+ BT_ASSERT(bt_field_get_type_id(string_field) == BT_FIELD_TYPE_ID_STRING);
+
+ /* Append character */
+ str[0] = (char) value;
+ ret = bt_field_string_append_with_length(string_field, str, 1);
+ if (ret) {
+ BT_LOGE("Cannot append character to string field's value: "
+ "notit-addr=%p, field-addr=%p, ret=%d",
+ notit, string_field, ret);
+ status = BT_BTR_STATUS_ERROR;
+ goto end;
+ }
end:
return status;
static
enum bt_btr_status btr_signed_int_cb(int64_t value,
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
struct bt_notif_iter *notit = data;
- int ret;
+ struct ctf_field_type_int *int_ft = (void *) ft;
BT_LOGV("Signed integer function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s, value=%" PRId64,
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
- value);
- field = borrow_next_field(notit);
- if (!field) {
- BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
- status = BT_BTR_STATUS_ERROR;
+ "ft-id=%d, ft-in-ir=%d, value=%" PRId64,
+ notit, notit->btr, ft, ft->id, ft->in_ir, value);
+ BT_ASSERT(int_ft->meaning == CTF_FIELD_TYPE_MEANING_NONE);
+
+ if (unlikely(int_ft->storing_index >= 0)) {
+ g_array_index(notit->stored_values, uint64_t,
+ (uint64_t) int_ft->storing_index) = (uint64_t) value;
+ }
+
+ if (unlikely(!ft->in_ir)) {
goto end;
}
- BT_ASSERT(bt_field_is_integer(field) || bt_field_is_enumeration(field));
- ret = bt_field_integer_signed_set_value(field, value);
- BT_ASSERT(ret == 0);
+ field = borrow_next_field(notit);
+ BT_ASSERT(field);
+ BT_ASSERT(bt_field_borrow_type(field) == ft->ir_ft);
+ BT_ASSERT(bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SIGNED_INTEGER ||
+ bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION);
+ bt_field_signed_integer_set_value(field, value);
stack_top(notit->stack)->index++;
end:
static
enum bt_btr_status btr_floating_point_cb(double value,
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
struct bt_notif_iter *notit = data;
- int ret;
BT_LOGV("Floating point number function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s, value=%f",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
- value);
+ "ft-id=%d, ft-in-ir=%d, value=%f",
+ notit, notit->btr, ft, ft->id, ft->in_ir, value);
+ BT_ASSERT(ft->in_ir);
field = borrow_next_field(notit);
- if (!field) {
- BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
- ret = bt_field_floating_point_set_value(field, value);
- BT_ASSERT(!ret);
+ BT_ASSERT(field);
+ BT_ASSERT(bt_field_borrow_type(field) == ft->ir_ft);
+ BT_ASSERT(bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_REAL);
+ bt_field_real_set_value(field, value);
stack_top(notit->stack)->index++;
-
-end:
return status;
}
static
enum bt_btr_status btr_string_begin_cb(
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
- enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
struct bt_notif_iter *notit = data;
int ret;
BT_LOGV("String (beginning) function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
- field = borrow_next_field(notit);
- if (!field) {
- BT_LOGW("Cannot get next field: notit-addr=%p", notit);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
+ "ft-id=%d, ft-in-ir=%d",
+ notit, notit->btr, ft, ft->id, ft->in_ir);
+ BT_ASSERT(ft->in_ir);
+ field = borrow_next_field(notit);
+ BT_ASSERT(field);
+ BT_ASSERT(bt_field_borrow_type(field) == ft->ir_ft);
+ BT_ASSERT(bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING);
ret = bt_field_string_clear(field);
BT_ASSERT(ret == 0);
/*
- * Push on stack. Not a compound type per se, but we know that only
- * btr_string_cb() may be called between this call and a subsequent
- * call to btr_string_end_cb().
+ * Push on stack. Not a compound type per se, but we know that
+ * only btr_string_cb() may be called between this call and a
+ * subsequent call to btr_string_end_cb().
*/
- ret = stack_push(notit->stack, field);
- if (ret) {
- BT_LOGE("Cannot push string field on stack: "
- "notit-addr=%p, field-addr=%p", notit, field);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
-
-end:
- return status;
+ stack_push(notit->stack, field);
+ return BT_BTR_STATUS_OK;
}
static
enum bt_btr_status btr_string_cb(const char *value,
- size_t len, struct bt_field_type *type, void *data)
+ size_t len, struct ctf_field_type *ft, void *data)
{
enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_field *field = NULL;
BT_LOGV("String (substring) function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s, string-length=%zu",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
+ "ft-id=%d, ft-in-ir=%d, string-length=%zu",
+ notit, notit->btr, ft, ft->id, ft->in_ir,
len);
+ BT_ASSERT(ft->in_ir);
field = stack_top(notit->stack)->base;
BT_ASSERT(field);
/* Append current substring */
- ret = bt_field_string_append_len(field, value, len);
+ ret = bt_field_string_append_with_length(field, value, len);
if (ret) {
BT_LOGE("Cannot append substring to string field's value: "
"notit-addr=%p, field-addr=%p, string-length=%zu, "
static
enum bt_btr_status btr_string_end_cb(
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
struct bt_notif_iter *notit = data;
BT_LOGV("String (end) function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
+ "ft-id=%d, ft-in-ir=%d",
+ notit, notit->btr, ft, ft->id, ft->in_ir);
+ BT_ASSERT(ft->in_ir);
/* Pop string field */
stack_pop(notit->stack);
}
enum bt_btr_status btr_compound_begin_cb(
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
- enum bt_btr_status status = BT_BTR_STATUS_OK;
struct bt_notif_iter *notit = data;
struct bt_field *field;
- int ret;
BT_LOGV("Compound (beginning) function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
+ "ft-id=%d, ft-in-ir=%d",
+ notit, notit->btr, ft, ft->id, ft->in_ir);
+
+ if (!ft->in_ir) {
+ goto end;
+ }
/* Borrow field */
if (stack_empty(notit->stack)) {
field = notit->cur_dscope_field;
} else {
field = borrow_next_field(notit);
- if (!field) {
- BT_LOGW("Cannot borrow next field: notit-addr=%p", notit);
- status = BT_BTR_STATUS_ERROR;
- goto end;
- }
+ BT_ASSERT(field);
}
/* Push field */
BT_ASSERT(field);
- ret = stack_push(notit->stack, field);
- if (ret) {
- BT_LOGE("Cannot push compound field onto the stack: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s, ret=%d",
- notit, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)),
- ret);
- status = BT_BTR_STATUS_ERROR;
- goto end;
+ BT_ASSERT(bt_field_borrow_type(field) == ft->ir_ft);
+ stack_push(notit->stack, field);
+
+ /*
+ * Change BTR "unsigned int" callback if it's a text
+ * array/sequence.
+ */
+ if (ft->id == CTF_FIELD_TYPE_ID_ARRAY ||
+ ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ if (array_ft->is_text) {
+ int ret;
+
+ BT_ASSERT(bt_field_get_type_id(field) ==
+ BT_FIELD_TYPE_ID_STRING);
+ notit->done_filling_string = false;
+ ret = bt_field_string_clear(field);
+ BT_ASSERT(ret == 0);
+ bt_btr_set_unsigned_int_cb(notit->btr,
+ btr_unsigned_int_char_cb);
+ }
}
end:
- return status;
+ return BT_BTR_STATUS_OK;
}
enum bt_btr_status btr_compound_end_cb(
- struct bt_field_type *type, void *data)
+ struct ctf_field_type *ft, void *data)
{
struct bt_notif_iter *notit = data;
BT_LOGV("Compound (end) function called from BTR: "
"notit-addr=%p, btr-addr=%p, ft-addr=%p, "
- "ft-id=%s",
- notit, notit->btr, type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(type)));
- BT_ASSERT(!stack_empty(notit->stack));
-
- /* Pop stack */
- stack_pop(notit->stack);
-
- /* If the stack is not empty, increment the base's index */
- if (!stack_empty(notit->stack)) {
- stack_top(notit->stack)->index++;
- }
-
- return BT_BTR_STATUS_OK;
-}
-
-static
-struct bt_field *resolve_field(struct bt_notif_iter *notit,
- struct bt_field_path *path)
-{
- struct bt_field *field = NULL;
- unsigned int i;
-
- if (BT_LOG_ON_VERBOSE) {
- GString *gstr = bt_field_path_string(path);
-
- BT_LOGV("Resolving field path: notit-addr=%p, field-path=\"%s\"",
- notit, gstr ? gstr->str : NULL);
-
- if (gstr) {
- g_string_free(gstr, TRUE);
- }
- }
-
- switch (bt_field_path_get_root_scope(path)) {
- case BT_SCOPE_TRACE_PACKET_HEADER:
- field = notit->dscopes.trace_packet_header;
- break;
- case BT_SCOPE_STREAM_PACKET_CONTEXT:
- field = notit->dscopes.stream_packet_context;
- break;
- case BT_SCOPE_STREAM_EVENT_HEADER:
- field = notit->dscopes.stream_event_header;
- break;
- case BT_SCOPE_STREAM_EVENT_CONTEXT:
- field = notit->dscopes.stream_event_context;
- break;
- case BT_SCOPE_EVENT_CONTEXT:
- field = notit->dscopes.event_context;
- break;
- case BT_SCOPE_EVENT_FIELDS:
- field = notit->dscopes.event_payload;
- break;
- default:
- BT_LOGF("Cannot resolve field path: unknown scope: "
- "notit-addr=%p, root-scope=%s",
- notit, bt_common_scope_string(
- bt_field_path_get_root_scope(path)));
- abort();
- }
+ "ft-id=%d, ft-in-ir=%d",
+ notit, notit->btr, ft, ft->id, ft->in_ir);
- if (!field) {
- BT_LOGW("Cannot resolve field path: root field not found: "
- "notit-addr=%p, root-scope=%s",
- notit, bt_common_scope_string(
- bt_field_path_get_root_scope(path)));
+ if (!ft->in_ir) {
goto end;
}
- for (i = 0; i < bt_field_path_get_index_count(path); ++i) {
- struct bt_field *next_field = NULL;
- struct bt_field_type *field_type;
- int index = bt_field_path_get_index(path, i);
-
- field_type = bt_field_borrow_type(field);
- BT_ASSERT(field_type);
+ BT_ASSERT(!stack_empty(notit->stack));
+ BT_ASSERT(bt_field_borrow_type(stack_top(notit->stack)->base) ==
+ ft->ir_ft);
- if (bt_field_type_is_structure(field_type)) {
- next_field = bt_field_structure_borrow_field_by_index(
- field, index);
- } else if (bt_field_type_is_variant(field_type)) {
- next_field =
- bt_field_variant_borrow_current_field(field);
+ /*
+ * Reset BTR "unsigned int" callback if it's a text
+ * array/sequence.
+ */
+ if (ft->id == CTF_FIELD_TYPE_ID_ARRAY ||
+ ft->id == CTF_FIELD_TYPE_ID_SEQUENCE) {
+ struct ctf_field_type_array_base *array_ft = (void *) ft;
+
+ if (array_ft->is_text) {
+ BT_ASSERT(bt_field_get_type_id(
+ stack_top(notit->stack)->base) ==
+ BT_FIELD_TYPE_ID_STRING);
+ bt_btr_set_unsigned_int_cb(notit->btr,
+ btr_unsigned_int_cb);
}
+ }
- field = NULL;
-
- if (!next_field) {
- BT_LOGW("Cannot find next field: "
- "notit-addr=%p, ft-addr=%p, ft-id=%s, index=%d",
- notit, field_type,
- bt_common_field_type_id_string(
- bt_field_type_get_type_id(field_type)),
- index);
- goto end;
- }
+ /* Pop stack */
+ stack_pop(notit->stack);
- /* Move next field -> field */
- field = next_field;
+ /* If the stack is not empty, increment the base's index */
+ if (!stack_empty(notit->stack)) {
+ stack_top(notit->stack)->index++;
}
end:
- return field;
+ return BT_BTR_STATUS_OK;
}
static
-int64_t btr_get_sequence_length_cb(struct bt_field_type *type, void *data)
+int64_t btr_get_sequence_length_cb(struct ctf_field_type *ft, void *data)
{
- int64_t ret = -1;
- int iret;
struct bt_field *seq_field;
- struct bt_field_path *field_path;
struct bt_notif_iter *notit = data;
- struct bt_field *length_field = NULL;
- uint64_t length;
-
- field_path = bt_field_type_sequence_borrow_length_field_path(type);
- BT_ASSERT(field_path);
- length_field = resolve_field(notit, field_path);
- if (!length_field) {
- BT_LOGW("Cannot resolve sequence field type's length field path: "
- "notit-addr=%p, ft-addr=%p",
- notit, type);
- goto end;
- }
-
- iret = bt_field_integer_unsigned_get_value(length_field, &length);
- if (iret) {
- BT_LOGE("Cannot get value of sequence length field: "
- "notit-addr=%p, field-addr=%p",
- notit, length_field);
- goto end;
- }
+ struct ctf_field_type_sequence *seq_ft = (void *) ft;
+ int64_t length = -1;
+ int ret;
+ length = (uint64_t) g_array_index(notit->stored_values, uint64_t,
+ seq_ft->stored_length_index);
seq_field = stack_top(notit->stack)->base;
- iret = bt_field_sequence_set_length(seq_field, length);
- if (iret) {
- BT_LOGE("Cannot set sequence field's length field: "
- "notit-addr=%p, seq-field-addr=%p, "
- "length=%" PRIu64,
- notit, seq_field, length);
- goto end;
+ BT_ASSERT(seq_field);
+ ret = bt_field_dynamic_array_set_length(seq_field, (uint64_t) length);
+ if (ret) {
+ BT_LOGE("Cannot set dynamic array field's length field: "
+ "notit-addr=%p, field-addr=%p, "
+ "length=%" PRIu64, notit, seq_field, length);
}
- ret = (int64_t) length;
-
-end:
- return ret;
+ return length;
}
static
-struct bt_field_type *btr_borrow_variant_field_type_cb(
- struct bt_field_type *type, void *data)
+struct ctf_field_type *btr_borrow_variant_selected_field_type_cb(
+ struct ctf_field_type *ft, void *data)
{
int ret;
- struct bt_field_path *path;
+ uint64_t i;
+ int64_t option_index = -1;
struct bt_notif_iter *notit = data;
- struct bt_field *var_field;
- struct bt_field *tag_field = NULL;
- struct bt_field_type *tag_ft = NULL;
- struct bt_field_type *tag_int_ft = NULL;
- struct bt_field *selected_field = NULL;
- struct bt_field_type *selected_field_type = NULL;
-
- path = bt_field_type_variant_borrow_tag_field_path(type);
- BT_ASSERT(path);
- tag_field = resolve_field(notit, path);
- if (!tag_field) {
- BT_LOGW("Cannot resolve variant field type's tag field path: "
- "notit-addr=%p, ft-addr=%p",
- notit, type);
- goto end;
- }
+ struct ctf_field_type_variant *var_ft = (void *) ft;
+ struct ctf_named_field_type *selected_option = NULL;
+ struct ctf_field_type *ret_ft = NULL;
+ union {
+ uint64_t u;
+ int64_t i;
+ } tag;
+
+ /* Get variant's tag */
+ tag.u = g_array_index(notit->stored_values, uint64_t,
+ var_ft->stored_tag_index);
/*
- * We found the enumeration tag field instance which should be
- * able to select a current field for this variant. This
- * callback function we're in is called _after_
- * compound_begin(), so the current stack top's base field is
- * the variant field in question. We set the variant field's tag
- * here and then get the current (selected) field thanks to this
- * tag field's value. This current field will also provide us
- * with its type. Then, this current field will remain the
- * current selected one until the next callback function call
- * which is used to fill it.
+ * Check each range to find the selected option's index.
*/
- var_field = stack_top(notit->stack)->base;
- tag_ft = bt_field_borrow_type(tag_field);
- tag_int_ft = bt_field_type_enumeration_borrow_container_field_type(
- tag_ft);
-
- if (bt_field_type_integer_is_signed(tag_int_ft)) {
- int64_t tag_value;
-
- ret = bt_field_integer_signed_get_value(tag_field, &tag_value);
- BT_ASSERT(ret == 0);
- ret = bt_field_variant_set_tag_signed(var_field, tag_value);
- BT_ASSERT(ret == 0);
+ if (var_ft->tag_ft->base.is_signed) {
+ for (i = 0; i < var_ft->ranges->len; i++) {
+ struct ctf_field_type_variant_range *range =
+ ctf_field_type_variant_borrow_range_by_index(
+ var_ft, i);
+
+ if (tag.i >= range->range.lower.i &&
+ tag.i <= range->range.upper.i) {
+ option_index = (int64_t) range->option_index;
+ break;
+ }
+ }
} else {
- uint64_t tag_value;
-
- ret = bt_field_integer_unsigned_get_value(tag_field,
- &tag_value);
- BT_ASSERT(ret == 0);
- ret = bt_field_variant_set_tag_unsigned(var_field, tag_value);
- BT_ASSERT(ret == 0);
+ for (i = 0; i < var_ft->ranges->len; i++) {
+ struct ctf_field_type_variant_range *range =
+ ctf_field_type_variant_borrow_range_by_index(
+ var_ft, i);
+
+ if (tag.u >= range->range.lower.u &&
+ tag.u <= range->range.upper.u) {
+ option_index = (int64_t) range->option_index;
+ break;
+ }
+ }
}
- selected_field = bt_field_variant_borrow_current_field(var_field);
- if (!selected_field) {
- BT_LOGW("Cannot borrow variant field's current field: "
- "notit-addr=%p, var-field-addr=%p",
- notit, var_field);
+ if (option_index < 0) {
+ BT_LOGW("Cannot find variant field type's option: "
+ "notit-addr=%p, var-ft-addr=%p, u-tag=%" PRIu64 ", "
+ "i-tag=%" PRId64, notit, var_ft, tag.u, tag.i);
goto end;
}
- selected_field_type = bt_field_borrow_type(selected_field);
+ selected_option = ctf_field_type_variant_borrow_option_by_index(
+ var_ft, (uint64_t) option_index);
-end:
- return selected_field_type;
-}
-
-static
-int set_event_clocks(struct bt_notif_iter *notit)
-{
- int ret;
- GHashTableIter iter;
- struct bt_clock_class *clock_class;
- uint64_t *clock_state;
-
- g_hash_table_iter_init(&iter, notit->clock_states);
+ if (selected_option->ft->in_ir) {
+ struct bt_field *var_field = stack_top(notit->stack)->base;
- while (g_hash_table_iter_next(&iter, (gpointer) &clock_class,
- (gpointer) &clock_state)) {
- ret = bt_event_set_clock_value(notit->event, clock_class,
- *clock_state, BT_TRUE);
+ ret = bt_field_variant_select_option_field(var_field,
+ option_index);
if (ret) {
- BT_LOGE("Cannot set event's default clock value: "
- "notit-addr=%p, clock-class-addr=%p, "
- "clock-class-name=\"%s\"",
- notit, clock_class,
- bt_clock_class_get_name(clock_class));
- ret = -1;
+ BT_LOGW("Cannot select variant field's option field: "
+ "notit-addr=%p, var-field-addr=%p, "
+ "opt-index=%" PRId64, notit, var_field,
+ option_index);
goto end;
}
}
- ret = 0;
+ ret_ft = selected_option->ft;
end:
- return ret;
+ return ret_ft;
+}
+
+static
+void set_event_default_clock_value(struct bt_notif_iter *notit)
+{
+ struct bt_event *event = bt_notification_event_borrow_event(
+ notit->event_notif);
+ struct bt_stream_class *sc = notit->meta.sc->ir_sc;
+
+ BT_ASSERT(event);
+
+ if (bt_stream_class_borrow_default_clock_class(sc)) {
+ int ret = bt_event_set_default_clock_value(event,
+ notit->default_clock_val);
+
+ BT_ASSERT(ret == 0);
+ }
}
static
int ret;
enum bt_notif_iter_status status;
struct bt_notification *notif = NULL;
+ struct bt_stream_class *sc;
status = set_current_packet(notit);
if (status != BT_NOTIF_ITER_STATUS_OK) {
}
BT_ASSERT(notit->packet);
+ sc = notit->meta.sc->ir_sc;
+ BT_ASSERT(sc);
+
+ if (bt_stream_class_packets_have_discarded_event_counter_snapshot(sc)) {
+ BT_ASSERT(notit->snapshots.discarded_events != UINT64_C(-1));
+ ret = bt_packet_set_discarded_event_counter_snapshot(
+ notit->packet, notit->snapshots.discarded_events);
+ BT_ASSERT(ret == 0);
+ }
+
+ if (bt_stream_class_packets_have_packet_counter_snapshot(sc)) {
+ BT_ASSERT(notit->snapshots.packets != UINT64_C(-1));
+ ret = bt_packet_set_packet_counter_snapshot(
+ notit->packet, notit->snapshots.packets);
+ BT_ASSERT(ret == 0);
+ }
+
+ if (bt_stream_class_packets_have_default_beginning_clock_value(sc)) {
+ BT_ASSERT(notit->snapshots.beginning_clock != UINT64_C(-1));
+ ret = bt_packet_set_default_beginning_clock_value(
+ notit->packet, notit->snapshots.beginning_clock);
+ BT_ASSERT(ret == 0);
+ }
+
+ if (bt_stream_class_packets_have_default_end_clock_value(sc)) {
+ BT_ASSERT(notit->snapshots.end_clock != UINT64_C(-1));
+ ret = bt_packet_set_default_end_clock_value(
+ notit->packet, notit->snapshots.end_clock);
+ BT_ASSERT(ret == 0);
+ }
if (notit->packet_header_field) {
- ret = bt_packet_move_header(notit->packet,
+ ret = bt_packet_move_header_field(notit->packet,
notit->packet_header_field);
if (ret) {
goto end;
* the same value as the packet header field within
* notit->packet.
*/
- BT_ASSERT(bt_packet_borrow_header(notit->packet) ==
+ BT_ASSERT(bt_packet_borrow_header_field(notit->packet) ==
notit->dscopes.trace_packet_header);
}
if (notit->packet_context_field) {
- ret = bt_packet_move_context(notit->packet,
+ ret = bt_packet_move_context_field(notit->packet,
notit->packet_context_field);
if (ret) {
goto end;
* the same value as the packet header field within
* notit->packet.
*/
- BT_ASSERT(bt_packet_borrow_context(notit->packet) ==
+ BT_ASSERT(bt_packet_borrow_context_field(notit->packet) ==
notit->dscopes.stream_packet_context);
}
return;
}
+ /* Update default clock from packet's end time */
+ if (notit->snapshots.end_clock != UINT64_C(-1)) {
+ notit->default_clock_val = notit->snapshots.end_clock;
+ }
+
BT_ASSERT(notit->notif_iter);
notif = bt_notification_packet_end_create(notit->notif_iter,
notit->packet);
}
- BT_MOVE(notit->prev_packet, notit->packet);
- notit->prev_packet_avail =
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE;
+ BT_PUT(notit->packet);
*notification = notif;
}
-static
-void init_trace_field_path_cache(struct bt_trace *trace,
- struct trace_field_path_cache *trace_field_path_cache)
-{
- int stream_id = -1;
- int stream_instance_id = -1;
- int i, count;
- struct bt_field_type *packet_header = NULL;
-
- packet_header = bt_trace_borrow_packet_header_field_type(trace);
- if (!packet_header) {
- goto end;
- }
-
- if (!bt_field_type_is_structure(packet_header)) {
- goto end;
- }
-
- count = bt_field_type_structure_get_field_count(packet_header);
- BT_ASSERT(count >= 0);
-
- for (i = 0; (i < count && (stream_id == -1 || stream_instance_id == -1)); i++) {
- int ret;
- const char *field_name;
-
- ret = bt_field_type_structure_borrow_field_by_index(
- packet_header, &field_name, NULL, i);
- if (ret) {
- BT_LOGE("Cannot get structure field's field: "
- "field-addr=%p, index=%d",
- packet_header, i);
- goto end;
- }
-
- if (stream_id == -1 && !strcmp(field_name, "stream_id")) {
- stream_id = i;
- } else if (stream_instance_id == -1 &&
- !strcmp(field_name, "stream_instance_id")) {
- stream_instance_id = i;
- }
- }
-
-end:
- trace_field_path_cache->stream_id = stream_id;
- trace_field_path_cache->stream_instance_id = stream_instance_id;
-}
-
BT_HIDDEN
-struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace,
+struct bt_notif_iter *bt_notif_iter_create(struct ctf_trace_class *tc,
size_t max_request_sz,
struct bt_notif_iter_medium_ops medops, void *data)
{
},
.query = {
.get_sequence_length = btr_get_sequence_length_cb,
- .borrow_variant_field_type = btr_borrow_variant_field_type_cb,
+ .borrow_variant_selected_field_type = btr_borrow_variant_selected_field_type_cb,
},
};
- BT_ASSERT(trace);
+ BT_ASSERT(tc);
BT_ASSERT(medops.request_bytes);
BT_ASSERT(medops.borrow_stream);
BT_LOGD("Creating CTF plugin notification iterator: "
"trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
- "data=%p",
- trace, bt_trace_get_name(trace), max_request_sz, data);
+ "data=%p", tc, tc->name->str, max_request_sz, data);
notit = g_new0(struct bt_notif_iter, 1);
if (!notit) {
BT_LOGE_STR("Failed to allocate one CTF plugin notification iterator.");
goto end;
}
- notit->clock_states = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, g_free);
- if (!notit->clock_states) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
- goto error;
- }
- notit->meta.trace = trace;
+ notit->meta.tc = tc;
notit->medium.medops = medops;
notit->medium.max_request_sz = max_request_sz;
notit->medium.data = data;
notit->stack = stack_new(notit);
+ notit->stored_values = g_array_new(FALSE, TRUE, sizeof(uint64_t));
+ g_array_set_size(notit->stored_values, tc->stored_value_count);
+
if (!notit->stack) {
BT_LOGE_STR("Failed to create field stack.");
goto error;
}
bt_notif_iter_reset(notit);
- init_trace_field_path_cache(trace, ¬it->trace_field_path_cache);
- notit->sc_field_path_caches = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, g_free);
- if (!notit->sc_field_path_caches) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
- goto error;
- }
-
- notit->field_overrides = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, g_free);
- if (!notit->field_overrides) {
- BT_LOGE_STR("Failed to allocate a GHashTable.");
- goto error;
- }
-
BT_LOGD("Created CTF plugin notification iterator: "
"trace-addr=%p, trace-name=\"%s\", max-request-size=%zu, "
"data=%p, notit-addr=%p",
- trace, bt_trace_get_name(trace), max_request_sz, data,
+ tc, tc->name->str, max_request_sz, data,
notit);
notit->cur_packet_offset = 0;
void bt_notif_iter_destroy(struct bt_notif_iter *notit)
{
BT_PUT(notit->packet);
- BT_PUT(notit->prev_packet);
BT_PUT(notit->stream);
release_all_dscopes(notit);
bt_btr_destroy(notit->btr);
}
- if (notit->clock_states) {
- g_hash_table_destroy(notit->clock_states);
- }
-
- if (notit->sc_field_path_caches) {
- g_hash_table_destroy(notit->sc_field_path_caches);
- }
-
- if (notit->field_overrides) {
- g_hash_table_destroy(notit->field_overrides);
+ if (notit->stored_values) {
+ g_array_free(notit->stored_values, TRUE);
}
g_free(notit);
struct bt_private_connection_private_notification_iterator *notif_iter,
struct bt_notification **notification)
{
- int ret;
enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
BT_ASSERT(notit);
case STATE_EMIT_NOTIF_NEW_STREAM:
/* notify_new_stream() logs errors */
notify_new_stream(notit, notification);
+
if (!*notification) {
status = BT_NOTIF_ITER_STATUS_ERROR;
}
+
notit->stream_begin_emitted = true;
goto end;
case STATE_EMIT_NOTIF_NEW_PACKET:
/* notify_new_packet() logs errors */
notify_new_packet(notit, notification);
+
if (!*notification) {
status = BT_NOTIF_ITER_STATUS_ERROR;
}
goto end;
case STATE_EMIT_NOTIF_EVENT:
BT_ASSERT(notit->event_notif);
- ret = set_event_clocks(notit);
- if (ret) {
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
- }
-
+ set_event_default_clock_value(notit);
*notification = notit->event_notif;
notit->event_notif = NULL;
goto end;
case STATE_EMIT_NOTIF_END_OF_PACKET:
- /* Update clock with timestamp_end field. */
- if (notit->cur_timestamp_end) {
- enum bt_btr_status btr_status;
-
- btr_status = update_clock(notit,
- notit->cur_timestamp_end);
- if (btr_status != BT_BTR_STATUS_OK) {
- BT_LOGW("Cannot update stream's clock value: "
- "notit-addr=%p", notit);
- status = BT_NOTIF_ITER_STATUS_ERROR;
- goto end;
- }
- }
-
/* notify_end_of_packet() logs errors */
notify_end_of_packet(notit, notification);
+
if (!*notification) {
status = BT_NOTIF_ITER_STATUS_ERROR;
}
}
medium_status = notit->medium.medops.seek(
- BT_NOTIF_ITER_SEEK_WHENCE_SET, offset,
- notit->medium.data);
+ BT_NOTIF_ITER_SEEK_WHENCE_SET, offset, notit->medium.data);
if (medium_status != BT_NOTIF_ITER_MEDIUM_STATUS_OK) {
if (medium_status == BT_NOTIF_ITER_MEDIUM_STATUS_EOF) {
ret = BT_NOTIF_ITER_STATUS_EOF;
bt_notif_iter_reset(notit);
notit->cur_packet_offset = offset;
+
end:
return ret;
}
BT_HIDDEN
-off_t bt_notif_iter_get_current_packet_offset(
- struct bt_notif_iter *notit)
+off_t bt_notif_iter_get_current_packet_offset(struct bt_notif_iter *notit)
{
BT_ASSERT(notit);
return notit->cur_packet_offset;
struct bt_notif_iter *notit)
{
BT_ASSERT(notit);
- return notit->cur_packet_size;
+ return notit->cur_exp_packet_total_size;
+}
+
+BT_HIDDEN
+void bt_notif_trace_class_changed(struct bt_notif_iter *notit)
+{
+ if (notit->meta.tc->stored_value_count > notit->stored_values->len) {
+ g_array_set_size(notit->stored_values,
+ notit->meta.tc->stored_value_count);
+ }
+}
+
+BT_HIDDEN
+enum bt_notif_iter_status bt_notif_iter_get_packet_properties(
+ struct bt_notif_iter *notit,
+ struct bt_notif_iter_packet_properties *props)
+{
+ BT_ASSERT(notit);
+ BT_ASSERT(props);
+
+ props->exp_packet_total_size =
+ (uint64_t) notit->cur_exp_packet_total_size;
+ props->exp_packet_content_size =
+ (uint64_t) notit->cur_exp_packet_content_size;
+ BT_ASSERT(props->stream_class_id >= 0);
+ props->stream_class_id = (uint64_t) notit->cur_stream_class_id;
+ props->data_stream_id = notit->cur_data_stream_id;
+ props->snapshots.discarded_events = notit->snapshots.discarded_events;
+ props->snapshots.packets = notit->snapshots.packets;
+ props->snapshots.beginning_clock = notit->snapshots.beginning_clock;
+ props->snapshots.end_clock = notit->snapshots.end_clock;
+ return BT_NOTIF_ITER_STATUS_OK;
}
#include <babeltrace/babeltrace.h>
#include <babeltrace/babeltrace-internal.h>
+#include "../metadata/ctf-meta.h"
+
/**
* @file ctf-notif-iter.h
*
*/
struct bt_stream * (* borrow_stream)(
struct bt_stream_class *stream_class,
- uint64_t stream_id, void *data);
+ int64_t stream_id, void *data);
};
/** CTF notification iterator. */
struct bt_notif_iter;
-// TODO: Replace by the real thing
-enum bt_notif_iter_notif_type {
- BT_NOTIF_ITER_NOTIF_NEW_PACKET,
- BT_NOTIF_ITER_NOTIF_END_OF_PACKET,
- BT_NOTIF_ITER_NOTIF_EVENT,
-};
-
-struct bt_notif_iter_notif {
- enum bt_notif_iter_notif_type type;
-};
-
-struct bt_notif_iter_notif_new_packet {
- struct bt_notif_iter_notif base;
- struct bt_packet *packet;
-};
-
-struct bt_notif_iter_notif_end_of_packet {
- struct bt_notif_iter_notif base;
- struct bt_packet *packet;
-};
-
-struct bt_notif_iter_notif_event {
- struct bt_notif_iter_notif base;
- struct bt_event *event;
-};
-
/**
* Creates a CTF notification iterator.
*
* success, or \c NULL on error
*/
BT_HIDDEN
-struct bt_notif_iter *bt_notif_iter_create(struct bt_trace *trace,
+struct bt_notif_iter *bt_notif_iter_create(struct ctf_trace_class *tc,
size_t max_request_sz, struct bt_notif_iter_medium_ops medops,
void *medops_data);
struct bt_field **packet_header_field,
struct bt_field **packet_context_field);
+struct bt_notif_iter_packet_properties {
+ uint64_t exp_packet_total_size;
+ uint64_t exp_packet_content_size;
+ uint64_t stream_class_id;
+ int64_t data_stream_id;
+
+ struct {
+ uint64_t discarded_events;
+ uint64_t packets;
+ uint64_t beginning_clock;
+ uint64_t end_clock;
+ } snapshots;
+};
+
+BT_HIDDEN
+enum bt_notif_iter_status bt_notif_iter_get_packet_properties(
+ struct bt_notif_iter *notit,
+ struct bt_notif_iter_packet_properties *props);
+
BT_HIDDEN
void bt_notif_iter_set_medops_data(struct bt_notif_iter *notit,
void *medops_data);
BT_HIDDEN
void bt_notif_iter_reset(struct bt_notif_iter *notit);
+/*
+ * Notify the iterator that the trace class changed somehow (new
+ * stream/event classes).
+ */
+BT_HIDDEN
+void bt_notif_trace_class_changed(struct bt_notif_iter *notit);
+
static inline
const char *bt_notif_iter_medium_status_string(
enum bt_notif_iter_medium_status status)
#include "logging.h"
#include "utils.h"
-
-struct bt_stream_class *ctf_utils_borrow_stream_class_from_packet_header(
- struct bt_trace *trace,
- struct bt_field *packet_header_field)
-{
- struct bt_field *stream_id_field = NULL;
- struct bt_stream_class *stream_class = NULL;
- uint64_t stream_id = -1ULL;
- int ret;
-
- if (!packet_header_field) {
- goto single_stream_class;
- }
-
- stream_id_field = bt_field_structure_borrow_field_by_name(
- packet_header_field, "stream_id");
- if (!stream_id_field) {
- goto single_stream_class;
- }
-
- ret = bt_field_integer_unsigned_get_value(stream_id_field,
- &stream_id);
- if (ret) {
- stream_id = -1ULL;
- }
-
- if (stream_id == -1ULL) {
-single_stream_class:
- /* Single stream class */
- if (bt_trace_get_stream_class_count(trace) == 0) {
- goto end;
- }
-
- stream_class = bt_trace_borrow_stream_class_by_index(trace, 0);
- } else {
- stream_class = bt_trace_borrow_stream_class_by_id(trace,
- stream_id);
- }
-
-end:
- return stream_class;
-}
#include <babeltrace/babeltrace.h>
#include <babeltrace/babeltrace-internal.h>
-struct bt_stream_class *ctf_utils_borrow_stream_class_from_packet_header(
- struct bt_trace *trace,
- struct bt_field *packet_header_field);
-
#endif /* CTF_UTILS_H */
static
struct bt_stream *medop_borrow_stream(
- struct bt_stream_class *stream_class, uint64_t stream_id,
+ struct bt_stream_class *stream_class, int64_t stream_id,
void *data)
{
struct ctf_fs_ds_file *ds_file = data;
index->entries->len - 1);
}
-static
-struct bt_clock_class *borrow_field_mapped_clock_class(
- struct bt_field *field)
-{
- struct bt_field_type *field_type;
- struct bt_clock_class *clock_class = NULL;
-
- field_type = bt_field_borrow_type(field);
- if (!field_type) {
- goto end;
- }
-
- clock_class = bt_field_type_integer_borrow_mapped_clock_class(
- field_type);
- if (!clock_class) {
- goto end;
- }
-
-end:
- return clock_class;
-}
-
-static
-int borrow_packet_bounds_from_packet_context(
- struct bt_field *packet_context,
- struct bt_clock_class **_timestamp_begin_cc,
- struct bt_field **_timestamp_begin,
- struct bt_clock_class **_timestamp_end_cc,
- struct bt_field **_timestamp_end)
-{
- int ret = 0;
- struct bt_clock_class *timestamp_begin_cc = NULL;
- struct bt_clock_class *timestamp_end_cc = NULL;
- struct bt_field *timestamp_begin = NULL;
- struct bt_field *timestamp_end = NULL;
-
- timestamp_begin = bt_field_structure_borrow_field_by_name(
- packet_context, "timestamp_begin");
- if (!timestamp_begin) {
- BT_LOGD_STR("Cannot retrieve timestamp_begin field in packet context.");
- ret = -1;
- goto end;
- }
-
- timestamp_begin_cc = borrow_field_mapped_clock_class(timestamp_begin);
- if (!timestamp_begin_cc) {
- BT_LOGD_STR("Cannot retrieve the clock mapped to timestamp_begin.");
- }
-
- timestamp_end = bt_field_structure_borrow_field_by_name(
- packet_context, "timestamp_end");
- if (!timestamp_end) {
- BT_LOGD_STR("Cannot retrieve timestamp_end field in packet context.");
- ret = -1;
- goto end;
- }
-
- timestamp_end_cc = borrow_field_mapped_clock_class(timestamp_end);
- if (!timestamp_end_cc) {
- BT_LOGD_STR("Cannot retrieve the clock mapped to timestamp_end.");
- }
-
- if (_timestamp_begin_cc) {
- *_timestamp_begin_cc = timestamp_begin_cc;
- }
- if (_timestamp_begin) {
- *_timestamp_begin = timestamp_begin;
- }
- if (_timestamp_end_cc) {
- *_timestamp_end_cc = timestamp_end_cc;
- }
- if (_timestamp_end) {
- *_timestamp_end = timestamp_end;
- }
-end:
- return ret;
-}
-
-static
-int borrow_ds_file_packet_bounds_clock_classes(struct ctf_fs_ds_file *ds_file,
- struct bt_clock_class **timestamp_begin_cc,
- struct bt_clock_class **timestamp_end_cc)
-{
- struct bt_field *packet_context = NULL;
- int ret = ctf_fs_ds_file_borrow_packet_header_context_fields(ds_file,
- NULL, &packet_context);
-
- if (ret || !packet_context) {
- BT_LOGD("Cannot retrieve packet context field: ds-file-path=\"%s\"",
- ds_file->file->path->str);
- ret = -1;
- goto end;
- }
-
- ret = borrow_packet_bounds_from_packet_context(packet_context,
- timestamp_begin_cc, NULL,
- timestamp_end_cc, NULL);
-
-end:
- return ret;
-}
-
static
int convert_cycles_to_ns(struct bt_clock_class *clock_class,
uint64_t cycles, int64_t *ns)
{
- return bt_clock_class_cycles_to_ns(clock_class, cycles, ns);
+ return bt_clock_class_cycles_to_ns_from_origin(clock_class, cycles, ns);
}
static
size_t file_index_entry_size;
size_t file_entry_count;
size_t i;
- struct bt_clock_class *timestamp_begin_cc = NULL;
- struct bt_clock_class *timestamp_end_cc = NULL;
+ struct ctf_stream_class *sc;
+ struct bt_notif_iter_packet_properties props;
BT_LOGD("Building index from .idx file of stream file %s",
ds_file->file->path->str);
- ret = borrow_ds_file_packet_bounds_clock_classes(ds_file,
- ×tamp_begin_cc, ×tamp_end_cc);
+ ret = bt_notif_iter_borrow_packet_header_context_fields(
+ ds_file->notif_iter, NULL, NULL);
if (ret) {
- BT_LOGD_STR("Cannot get clock classes of \"timestamp_begin\" "
- "and \"timestamp_end\" fields");
+ BT_LOGD_STR("Cannot borrow first packet's header and context "
+ "fields.");
+ goto error;
+ }
+
+ ret = bt_notif_iter_get_packet_properties(ds_file->notif_iter, &props);
+ BT_ASSERT(ret == 0);
+ sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc,
+ props.stream_class_id);
+ BT_ASSERT(sc);
+ if (!sc->default_clock_class) {
+ BT_LOGD_STR("Cannot find stream class's default clock class.");
goto error;
}
}
/* Convert the packet's bound to nanoseconds since Epoch. */
- ret = convert_cycles_to_ns(timestamp_begin_cc,
+ ret = convert_cycles_to_ns(sc->default_clock_class,
index_entry->timestamp_begin,
&index_entry->timestamp_begin_ns);
if (ret) {
BT_LOGD_STR("Failed to convert raw timestamp to nanoseconds since Epoch during index parsing");
goto error;
}
- ret = convert_cycles_to_ns(timestamp_end_cc,
+ ret = convert_cycles_to_ns(sc->default_clock_class,
index_entry->timestamp_end,
&index_entry->timestamp_end_ns);
if (ret) {
static
int init_index_entry(struct ctf_fs_ds_index_entry *entry,
- struct bt_field *packet_context, off_t packet_size,
- off_t packet_offset)
+ struct ctf_fs_ds_file *ds_file,
+ struct bt_notif_iter_packet_properties *props,
+ off_t packet_size, off_t packet_offset)
{
int ret;
- struct bt_field *timestamp_begin = NULL;
- struct bt_field *timestamp_end = NULL;
- struct bt_clock_class *timestamp_begin_cc = NULL;
- struct bt_clock_class *timestamp_end_cc = NULL;
-
- ret = borrow_packet_bounds_from_packet_context(packet_context,
- ×tamp_begin_cc, ×tamp_begin,
- ×tamp_end_cc, ×tamp_end);
- if (ret || !timestamp_begin_cc || !timestamp_begin ||
- !timestamp_end_cc || ! timestamp_end) {
- BT_LOGD_STR("Failed to determine time bound fields of packet.");
- goto end;
- }
+ struct ctf_stream_class *sc;
+ sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc,
+ props->stream_class_id);
+ BT_ASSERT(sc);
BT_ASSERT(packet_offset >= 0);
entry->offset = packet_offset;
-
BT_ASSERT(packet_size >= 0);
entry->packet_size = packet_size;
- ret = bt_field_integer_unsigned_get_value(timestamp_begin,
- &entry->timestamp_begin);
- if (ret) {
- goto end;
- }
- ret = bt_field_integer_unsigned_get_value(timestamp_end,
- &entry->timestamp_end);
- if (ret) {
- goto end;
- }
-
/* Convert the packet's bound to nanoseconds since Epoch. */
- ret = convert_cycles_to_ns(timestamp_begin_cc,
- entry->timestamp_begin,
+ ret = convert_cycles_to_ns(sc->default_clock_class,
+ props->snapshots.beginning_clock,
&entry->timestamp_begin_ns);
if (ret) {
BT_LOGD_STR("Failed to convert raw timestamp to nanoseconds since Epoch.");
goto end;
}
- ret = convert_cycles_to_ns(timestamp_end_cc,
- entry->timestamp_end,
+ ret = convert_cycles_to_ns(sc->default_clock_class,
+ props->snapshots.end_clock,
&entry->timestamp_end_ns);
if (ret) {
BT_LOGD_STR("Failed to convert raw timestamp to nanoseconds since Epoch.");
do {
off_t current_packet_offset;
off_t next_packet_offset;
- off_t current_packet_size, current_packet_size_bytes;
+ off_t current_packet_size_bytes;
struct ctf_fs_ds_index_entry *entry;
- struct bt_field *packet_context = NULL;
+ struct bt_notif_iter_packet_properties props;
iter_status = bt_notif_iter_borrow_packet_header_context_fields(
- ds_file->notif_iter, NULL, &packet_context);
+ ds_file->notif_iter, NULL, NULL);
if (iter_status != BT_NOTIF_ITER_STATUS_OK) {
if (iter_status == BT_NOTIF_ITER_STATUS_EOF) {
break;
goto error;
}
+ ret = bt_notif_iter_get_packet_properties(ds_file->notif_iter,
+ &props);
+ BT_ASSERT(ret == 0);
+
current_packet_offset =
bt_notif_iter_get_current_packet_offset(
ds_file->notif_iter);
goto error;
}
- current_packet_size = bt_notif_iter_get_current_packet_size(
- ds_file->notif_iter);
- if (current_packet_size < 0) {
- BT_LOGE("Cannot get packet size: packet-offset=%jd",
- current_packet_offset);
- goto error;
- }
current_packet_size_bytes =
- ((current_packet_size + 7) & ~7) / CHAR_BIT;
+ ((props.exp_packet_total_size + 7) & ~7) / CHAR_BIT;
if (current_packet_offset + current_packet_size_bytes >
ds_file->file->size) {
goto error;
}
- ret = init_index_entry(entry, packet_context,
- current_packet_size_bytes,
- current_packet_offset);
+ ret = init_index_entry(entry, ds_file, &props,
+ current_packet_size_bytes, current_packet_offset);
if (ret) {
goto error;
}
}
ds_file->stream = bt_get(stream);
- ds_file->cc_prio_map = bt_get(ctf_fs_trace->cc_prio_map);
+ ds_file->metadata = ctf_fs_trace->metadata;
g_string_assign(ds_file->file->path, path);
ret = ctf_fs_file_open(ds_file->file, "rb");
if (ret) {
status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
break;
}
-
return status;
}
GString *path;
/* Guaranteed to be set, as opposed to the index. */
- uint64_t begin_ns;
+ int64_t begin_ns;
};
+struct ctf_fs_metadata;
+
struct ctf_fs_ds_file {
+ /* Weak */
+ struct ctf_fs_metadata *metadata;
+
/* Weak */
struct bt_private_connection_private_notification_iterator *pc_notif_iter;
notif_iter_data->pc_notif_iter = it;
notif_iter_data->notif_iter = bt_notif_iter_create(
- port_data->ds_file_group->ctf_fs_trace->metadata->trace,
+ port_data->ds_file_group->ctf_fs_trace->metadata->tc,
bt_common_get_page_size() * 8,
ctf_fs_ds_file_medops, NULL);
if (!notif_iter_data->notif_iter) {
g_free(ctf_fs_trace->metadata);
}
- bt_put(ctf_fs_trace->cc_prio_map);
g_free(ctf_fs_trace);
}
return ret;
}
-static
-uint64_t get_packet_header_stream_instance_id(struct ctf_fs_trace *ctf_fs_trace,
- struct bt_field *packet_header_field)
-{
- struct bt_field *stream_instance_id_field = NULL;
- uint64_t stream_instance_id = -1ULL;
- int ret;
-
- if (!packet_header_field) {
- goto end;
- }
-
- stream_instance_id_field = bt_field_structure_borrow_field_by_name(
- packet_header_field, "stream_instance_id");
- if (!stream_instance_id_field) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
- &stream_instance_id);
- if (ret) {
- stream_instance_id = -1ULL;
- goto end;
- }
-
-end:
- return stream_instance_id;
-}
-
-uint64_t get_packet_context_timestamp_begin_ns(
- struct ctf_fs_trace *ctf_fs_trace,
- struct bt_field *packet_context_field)
-{
- int ret;
- struct bt_field *timestamp_begin_field = NULL;
- struct bt_field_type *timestamp_begin_ft = NULL;
- uint64_t timestamp_begin_raw_value = -1ULL;
- uint64_t timestamp_begin_ns = -1ULL;
- int64_t timestamp_begin_ns_signed;
- struct bt_clock_class *timestamp_begin_clock_class = NULL;
-
- if (!packet_context_field) {
- goto end;
- }
-
- timestamp_begin_field = bt_field_structure_borrow_field_by_name(
- packet_context_field, "timestamp_begin");
- if (!timestamp_begin_field) {
- goto end;
- }
-
- timestamp_begin_ft = bt_field_borrow_type(timestamp_begin_field);
- BT_ASSERT(timestamp_begin_ft);
- timestamp_begin_clock_class =
- bt_field_type_integer_borrow_mapped_clock_class(timestamp_begin_ft);
- if (!timestamp_begin_clock_class) {
- goto end;
- }
-
- ret = bt_field_integer_unsigned_get_value(timestamp_begin_field,
- ×tamp_begin_raw_value);
- if (ret) {
- goto end;
- }
-
- ret = bt_clock_class_cycles_to_ns(timestamp_begin_clock_class,
- timestamp_begin_raw_value, ×tamp_begin_ns_signed);
- if (ret) {
- goto end;
- }
-
- timestamp_begin_ns = (uint64_t) timestamp_begin_ns_signed;
-
-end:
- return timestamp_begin_ns;
-}
-
static
void ctf_fs_ds_file_info_destroy(struct ctf_fs_ds_file_info *ds_file_info)
{
static
struct ctf_fs_ds_file_info *ctf_fs_ds_file_info_create(const char *path,
- uint64_t begin_ns, struct ctf_fs_ds_index *index)
+ int64_t begin_ns, struct ctf_fs_ds_index *index)
{
struct ctf_fs_ds_file_info *ds_file_info;
static
int ctf_fs_ds_file_group_add_ds_file_info(
struct ctf_fs_ds_file_group *ds_file_group,
- const char *path, uint64_t begin_ns,
+ const char *path, int64_t begin_ns,
struct ctf_fs_ds_index *index)
{
struct ctf_fs_ds_file_info *ds_file_info;
int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace,
struct bt_graph *graph, const char *path)
{
- struct bt_field *packet_header_field = NULL;
- struct bt_field *packet_context_field = NULL;
struct bt_stream_class *stream_class = NULL;
- uint64_t stream_instance_id = -1ULL;
- uint64_t begin_ns = -1ULL;
+ int64_t stream_instance_id = -1;
+ int64_t begin_ns = -1;
struct ctf_fs_ds_file_group *ds_file_group = NULL;
bool add_group = false;
int ret;
struct ctf_fs_ds_file *ds_file = NULL;
struct ctf_fs_ds_index *index = NULL;
struct bt_notif_iter *notif_iter = NULL;
+ struct ctf_stream_class *sc = NULL;
+ struct bt_notif_iter_packet_properties props;
- notif_iter = bt_notif_iter_create(ctf_fs_trace->metadata->trace,
+ notif_iter = bt_notif_iter_create(ctf_fs_trace->metadata->tc,
bt_common_get_page_size() * 8, ctf_fs_ds_file_medops, NULL);
if (!notif_iter) {
BT_LOGE_STR("Cannot create a CTF notification iterator.");
}
ret = ctf_fs_ds_file_borrow_packet_header_context_fields(ds_file,
- &packet_header_field, &packet_context_field);
+ NULL, NULL);
if (ret) {
BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).",
path);
goto error;
}
- stream_instance_id = get_packet_header_stream_instance_id(ctf_fs_trace,
- packet_header_field);
- begin_ns = get_packet_context_timestamp_begin_ns(ctf_fs_trace,
- packet_context_field);
- stream_class = ctf_utils_borrow_stream_class_from_packet_header(
- ctf_fs_trace->metadata->trace, packet_header_field);
- if (!stream_class) {
- goto error;
+ ret = bt_notif_iter_get_packet_properties(ds_file->notif_iter, &props);
+ BT_ASSERT(ret == 0);
+ sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc,
+ props.stream_class_id);
+ BT_ASSERT(sc);
+ stream_class = sc->ir_sc;
+ BT_ASSERT(stream_class);
+ stream_instance_id = props.data_stream_id;
+
+ if (props.snapshots.beginning_clock != UINT64_C(-1)) {
+ BT_ASSERT(sc->default_clock_class);
+ ret = bt_clock_class_cycles_to_ns_from_origin(
+ sc->default_clock_class,
+ props.snapshots.beginning_clock, &begin_ns);
+ if (ret) {
+ BT_LOGE("Cannot convert clock cycles to nanoseconds from origin (`%s`).",
+ path);
+ goto error;
+ }
}
index = ctf_fs_ds_file_build_index(ds_file);
ds_file->file->path->str);
}
- if (begin_ns == -1ULL) {
+ if (begin_ns == -1) {
/*
* No beggining timestamp to sort the stream files
* within a stream file group, so consider that this
* file must be the only one within its group.
*/
- stream_instance_id = -1ULL;
+ stream_instance_id = -1;
}
- if (stream_instance_id == -1ULL) {
+ if (stream_instance_id == -1) {
/*
* No stream instance ID or no beginning timestamp:
* create a unique stream file group for this stream
goto end;
}
- BT_ASSERT(stream_instance_id != -1ULL);
- BT_ASSERT(begin_ns != -1ULL);
+ BT_ASSERT(stream_instance_id != -1);
+ BT_ASSERT(begin_ns != -1);
/* Find an existing stream file group with this ID */
for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
goto error;
}
- if (ds_file_group->stream_id == -1ULL) {
+ if (ds_file_group->stream_id == UINT64_C(-1)) {
/* No stream ID: use 0 */
- ds_file_group->stream = bt_stream_create(
- ds_file_group->stream_class, name->str,
+ ds_file_group->stream = bt_stream_create_with_id(
+ ds_file_group->stream_class,
ctf_fs_trace->next_stream_id);
ctf_fs_trace->next_stream_id++;
} else {
/* Specific stream ID */
- ds_file_group->stream = bt_stream_create(
- ds_file_group->stream_class, name->str,
- ds_file_group->stream_id);
+ ds_file_group->stream = bt_stream_create_with_id(
+ ds_file_group->stream_class,
+ (uint64_t) ds_file_group->stream_id);
}
- g_string_free(name, TRUE);
-
if (!ds_file_group->stream) {
BT_LOGE("Cannot create stream for DS file group: "
"addr=%p, stream-name=\"%s\"",
ds_file_group, name->str);
+ g_string_free(name, TRUE);
+ goto error;
+ }
+
+ ret = bt_stream_set_name(ds_file_group->stream, name->str);
+ if (ret) {
+ BT_LOGE("Cannot set stream's name: "
+ "addr=%p, stream-name=\"%s\"",
+ ds_file_group->stream, name->str);
+ g_string_free(name, TRUE);
goto error;
}
+
+ g_string_free(name, TRUE);
}
goto end;
goto error;
}
+ ctf_fs_metadata_init(ctf_fs_trace->metadata);
ctf_fs_trace->ds_file_groups = g_ptr_array_new_with_free_func(
(GDestroyNotify) ctf_fs_ds_file_group_destroy);
if (!ctf_fs_trace->ds_file_groups) {
* trace needs. There won't be any more. Therefore it is safe to
* make this trace static.
*/
- (void) bt_trace_set_is_static(ctf_fs_trace->metadata->trace);
+ (void) bt_trace_make_static(ctf_fs_trace->metadata->trace);
goto end;
error:
ctf_fs_trace_destroy(ctf_fs_trace);
ctf_fs_trace = NULL;
+
end:
return ctf_fs_trace;
}
#include <babeltrace/babeltrace.h>
#include "data-stream-file.h"
#include "metadata.h"
+#include "../common/metadata/decoder.h"
BT_HIDDEN
extern bool ctf_fs_debug;
};
struct ctf_fs_metadata {
+ /* Owned by this */
+ struct ctf_metadata_decoder *decoder;
+
/* Owned by this */
struct bt_trace *trace;
+ /* Weak (owned by `decoder` above) */
+ struct ctf_trace_class *tc;
+
+ /* Owned by this */
+
/* Owned by this */
char *text;
/* Owned by this */
struct ctf_fs_metadata *metadata;
- /* Owned by this */
- struct bt_clock_class_priority_map *cc_prio_map;
-
/* Array of struct ctf_fs_ds_file_group *, owned by this */
GPtrArray *ds_file_groups;
{
int ret = 0;
struct ctf_fs_file *file = NULL;
- struct ctf_metadata_decoder *metadata_decoder = NULL;
struct ctf_metadata_decoder_config decoder_config = {
.clock_class_offset_s = config ? config->clock_class_offset_s : 0,
.clock_class_offset_ns = config ? config->clock_class_offset_ns : 0,
goto end;
}
- metadata_decoder = ctf_metadata_decoder_create(
+ ctf_fs_trace->metadata->decoder = ctf_metadata_decoder_create(
config ? &decoder_config : NULL,
ctf_fs_trace->name->str);
- if (!metadata_decoder) {
+ if (!ctf_fs_trace->metadata->decoder) {
BT_LOGE("Cannot create metadata decoder object");
ret = -1;
goto end;
}
- ret = ctf_metadata_decoder_decode(metadata_decoder, file->fp);
+ ret = ctf_metadata_decoder_decode(ctf_fs_trace->metadata->decoder,
+ file->fp);
if (ret) {
BT_LOGE("Cannot decode metadata file");
goto end;
}
- ctf_fs_trace->metadata->trace = ctf_metadata_decoder_get_trace(
- metadata_decoder);
+ ctf_fs_trace->metadata->trace = ctf_metadata_decoder_get_ir_trace(
+ ctf_fs_trace->metadata->decoder);
BT_ASSERT(ctf_fs_trace->metadata->trace);
+ ctf_fs_trace->metadata->tc =
+ ctf_metadata_decoder_borrow_ctf_trace_class(
+ ctf_fs_trace->metadata->decoder);
+ BT_ASSERT(ctf_fs_trace->metadata->tc);
end:
ctf_fs_file_destroy(file);
- ctf_metadata_decoder_destroy(metadata_decoder);
return ret;
}
if (metadata->trace) {
BT_PUT(metadata->trace);
}
+
+ if (metadata->decoder) {
+ ctf_metadata_decoder_destroy(metadata->decoder);
+ }
}
struct bt_clock_class_priority_map *cc_prio_map;
};
-static
-struct bt_field_type *create_packet_header_ft(void)
-{
- struct bt_field_type *root_ft = NULL;
- struct bt_field_type *ft = NULL;
- int ret;
-
- root_ft = bt_field_type_structure_create();
- if (!root_ft) {
- BT_LOGE_STR("Cannot create an empty structure field type object.");
- goto error;
- }
-
- ft = bt_field_type_integer_create(32);
- if (!ft) {
- BT_LOGE_STR("Cannot create an integer field type object.");
- goto error;
- }
-
- ret = bt_field_type_structure_add_field(root_ft, ft, "magic");
- if (ret) {
- BT_LOGE("Cannot add `magic` field type to structure field type: "
- "ret=%d", ret);
- goto error;
- }
-
- BT_PUT(ft);
- ft = bt_field_type_integer_create(8);
- if (!ft) {
- BT_LOGE_STR("Cannot create an integer field type object.");
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(root_ft);
-
-end:
- bt_put(ft);
- return root_ft;
-}
-
-static
-struct bt_field_type *create_event_header_ft(
- struct bt_clock_class *clock_class)
-{
- struct bt_field_type *root_ft = NULL;
- struct bt_field_type *ft = NULL;
- int ret;
-
- root_ft = bt_field_type_structure_create();
- if (!root_ft) {
- BT_LOGE_STR("Cannot create an empty structure field type object.");
- goto error;
- }
-
- ft = bt_field_type_integer_create(64);
- if (!ft) {
- BT_LOGE_STR("Cannot create an integer field type object.");
- goto error;
- }
-
- ret = bt_field_type_integer_set_mapped_clock_class(ft, clock_class);
- if (ret) {
- BT_LOGE("Cannot map integer field type to clock class: "
- "ret=%d", ret);
- goto error;
- }
-
- ret = bt_field_type_structure_add_field(root_ft,
- ft, "timestamp");
- if (ret) {
- BT_LOGE("Cannot add `timestamp` field type to structure field type: "
- "ret=%d", ret);
- goto error;
- }
-
- goto end;
-
-error:
- BT_PUT(root_ft);
-
-end:
- bt_put(ft);
- return root_ft;
-}
-
static
struct bt_field_type *create_event_payload_ft(void)
{
goto error;
}
- ret = bt_field_type_structure_add_field(root_ft,
- ft, "str");
+ ret = bt_field_type_structure_append_member(root_ft, "str", ft);
if (ret) {
- BT_LOGE("Cannot add `str` field type to structure field type: "
+ BT_LOGE("Cannot add `str` member to structure field type: "
"ret=%d", ret);
goto error;
}
return root_ft;
}
-static
-struct bt_clock_class *create_clock_class(void)
-{
- return bt_clock_class_create("the_clock", 1000000000);
-}
-
static
int create_meta(struct dmesg_component *dmesg_comp, bool has_ts)
{
goto error;
}
- ft = create_packet_header_ft();
- if (!ft) {
- BT_LOGE_STR("Cannot create packet header field type.");
- goto error;
- }
-
- ret = bt_trace_set_packet_header_field_type(dmesg_comp->trace, ft);
- if (ret) {
- BT_LOGE_STR("Cannot set trace's packet header field type.");
- goto error;
- }
-
if (dmesg_comp->params.read_from_stdin) {
trace_name = "STDIN";
} else {
}
}
- dmesg_comp->stream_class = bt_stream_class_create(NULL);
+ dmesg_comp->stream_class = bt_stream_class_create(dmesg_comp->trace);
if (!dmesg_comp->stream_class) {
- BT_LOGE_STR("Cannot create an empty stream class object.");
+ BT_LOGE_STR("Cannot create a stream class object.");
goto error;
}
if (has_ts) {
- dmesg_comp->clock_class = create_clock_class();
+ dmesg_comp->clock_class = bt_clock_class_create();
if (!dmesg_comp->clock_class) {
BT_LOGE_STR("Cannot create clock class.");
goto error;
}
- ret = bt_trace_add_clock_class(dmesg_comp->trace,
- dmesg_comp->clock_class);
- if (ret) {
- BT_LOGE_STR("Cannot add clock class to trace.");
- goto error;
- }
-
- bt_put(ft);
- ft = create_event_header_ft(dmesg_comp->clock_class);
- if (!ft) {
- BT_LOGE_STR("Cannot create event header field type.");
- goto error;
- }
-
- ret = bt_stream_class_set_event_header_field_type(
- dmesg_comp->stream_class, ft);
+ ret = bt_stream_class_set_default_clock_class(
+ dmesg_comp->stream_class, dmesg_comp->clock_class);
if (ret) {
- BT_LOGE_STR("Cannot set stream class's event header field type.");
+ BT_LOGE_STR("Cannot set stream class's default clock class.");
goto error;
}
}
- dmesg_comp->event_class = bt_event_class_create("string");
+ dmesg_comp->event_class = bt_event_class_create(
+ dmesg_comp->stream_class);
if (!dmesg_comp->event_class) {
- BT_LOGE_STR("Cannot create an empty event class object.");
+ BT_LOGE_STR("Cannot create an event class object.");
+ goto error;
+ }
+
+ ret = bt_event_class_set_name(dmesg_comp->event_class, "string");
+ if (ret) {
+ BT_LOGE_STR("Cannot set event class's name.");
goto error;
}
- bt_put(ft);
ft = create_event_payload_ft();
if (!ft) {
BT_LOGE_STR("Cannot create event payload field type.");
goto error;
}
- ret = bt_stream_class_add_event_class(dmesg_comp->stream_class,
- dmesg_comp->event_class);
- if (ret) {
- BT_LOGE("Cannot add event class to stream class: ret=%d", ret);
- goto error;
- }
-
- ret = bt_trace_add_stream_class(dmesg_comp->trace,
- dmesg_comp->stream_class);
- if (ret) {
- BT_LOGE("Cannot add event class to stream class: ret=%d", ret);
- goto error;
- }
-
goto end;
error:
return ret;
}
-static
-int fill_packet_header_field(struct bt_packet *packet)
-{
- struct bt_field *ph = NULL;
- struct bt_field *magic = NULL;
- int ret;
-
- ph = bt_packet_borrow_header(packet);
- BT_ASSERT(ph);
- magic = bt_field_structure_borrow_field_by_name(ph, "magic");
- if (!magic) {
- BT_LOGE_STR("Cannot borrow `magic` field from structure field.");
- goto error;
- }
-
- ret = bt_field_integer_unsigned_set_value(magic, 0xc1fc1fc1);
- BT_ASSERT(ret == 0);
- goto end;
-
-error:
- ret = -1;
-
-end:
- return ret;
-}
-
static
int create_packet_and_stream(struct dmesg_component *dmesg_comp)
{
int ret = 0;
- dmesg_comp->stream = bt_stream_create(dmesg_comp->stream_class,
- NULL, 0);
+ dmesg_comp->stream = bt_stream_create(dmesg_comp->stream_class);
if (!dmesg_comp->stream) {
BT_LOGE_STR("Cannot create stream object.");
goto error;
}
- dmesg_comp->packet = bt_packet_create(dmesg_comp->stream,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
+ dmesg_comp->packet = bt_packet_create(dmesg_comp->stream);
if (!dmesg_comp->packet) {
BT_LOGE_STR("Cannot create packet object.");
goto error;
}
- ret = fill_packet_header_field(dmesg_comp->packet);
- if (ret) {
- BT_LOGE_STR("Cannot fill packet header field.");
- goto error;
- }
-
- ret = bt_trace_set_is_static(dmesg_comp->trace);
+ ret = bt_trace_make_static(dmesg_comp->trace);
if (ret) {
BT_LOGE_STR("Cannot make trace static.");
goto error;
unsigned long sec, usec, msec;
unsigned int year, mon, mday, hour, min;
uint64_t ts = 0;
- struct bt_field *eh_field = NULL;
- struct bt_field *ts_field = NULL;
int ret = 0;
struct dmesg_component *dmesg_comp = notif_iter->dmesg_comp;
BT_ASSERT(event);
if (dmesg_comp->clock_class) {
- ret = bt_event_set_clock_value(event,
- dmesg_comp->clock_class, ts, BT_TRUE);
- BT_ASSERT(ret == 0);
- eh_field = bt_event_borrow_header(event);
- BT_ASSERT(eh_field);
- ts_field = bt_field_structure_borrow_field_by_name(eh_field,
- "timestamp");
- if (!ts_field) {
- BT_LOGE_STR("Cannot borrow `timestamp` field from event header structure field.");
- goto error;
- }
-
- ret = bt_field_integer_unsigned_set_value(ts_field, ts);
+ ret = bt_event_set_default_clock_value(event, ts);
BT_ASSERT(ret == 0);
}
size_t len;
int ret;
- ep_field = bt_event_borrow_payload(event);
+ ep_field = bt_event_borrow_payload_field(event);
BT_ASSERT(ep_field);
- str_field = bt_field_structure_borrow_field_by_name(ep_field, "str");
+ str_field = bt_field_structure_borrow_member_field_by_index(ep_field,
+ 0);
if (!str_field) {
BT_LOGE_STR("Cannot borrow `timestamp` field from event payload structure field.");
goto error;
goto error;
}
- ret = bt_field_string_append_len(str_field, line, len);
+ ret = bt_field_string_append_with_length(str_field, line, len);
if (ret) {
BT_LOGE("Cannot append value to string field object: "
"len=%zu", len);
void print_timestamp_cycles(struct pretty_component *pretty,
struct bt_event *event)
{
- int ret;
struct bt_clock_value *clock_value;
uint64_t cycles;
+ enum bt_clock_value_status cv_status;
- clock_value = bt_event_borrow_default_clock_value(event);
- if (!clock_value) {
+ cv_status = bt_event_borrow_default_clock_value(event, &clock_value);
+ if (cv_status != BT_CLOCK_VALUE_STATUS_KNOWN || !clock_value) {
g_string_append(pretty->string, "????????????????????");
return;
}
- ret = bt_clock_value_get_value(clock_value, &cycles);
- if (ret) {
- // TODO: log, this is unexpected
- g_string_append(pretty->string, "Error");
- return;
- }
-
+ cycles = bt_clock_value_get_value(clock_value);
g_string_append_printf(pretty->string, "%020" PRIu64, cycles);
if (pretty->last_cycles_timestamp != -1ULL) {
return;
}
- ret = bt_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
+ ret = bt_clock_value_get_ns_from_origin(clock_value, &ts_nsec);
if (ret) {
// TODO: log, this is unexpected
g_string_append(pretty->string, "Error");
struct bt_stream_class *stream_class = NULL;
struct bt_trace *trace = NULL;
struct bt_clock_value *clock_value = NULL;
+ enum bt_clock_value_status cv_status;
stream = bt_event_borrow_stream(event);
if (!stream) {
goto end;
}
- clock_value = bt_event_borrow_default_clock_value(event);
- if (!clock_value) {
+ cv_status = bt_event_borrow_default_clock_value(event, &clock_value);
+ if (cv_status != BT_CLOCK_VALUE_STATUS_KNOWN || !clock_value) {
/* No default clock value: skip the timestamp without an error */
goto end;
}
if (pretty->options.print_timestamp_cycles) {
print_timestamp_cycles(pretty, event);
} else {
- struct bt_clock_value *clock_value =
- bt_event_borrow_default_clock_value(event);
-
+ clock_value = NULL;
+ cv_status = bt_event_borrow_default_clock_value(event,
+ &clock_value);
print_timestamp_wall(pretty, clock_value);
}
if (pretty->use_colors) {
struct bt_stream_class *stream_class = NULL;
struct bt_trace *trace_class = NULL;
int dom_print = 0;
+ enum bt_property_availability prop_avail;
event_class = bt_event_borrow_class(event);
if (!event_class) {
if (pretty->options.print_trace_hostname_field) {
struct bt_value *hostname_str;
- hostname_str = bt_trace_borrow_environment_field_value_by_name(
+ hostname_str = bt_trace_borrow_environment_entry_value_by_name(
trace_class, "hostname");
if (hostname_str) {
const char *str;
if (pretty->options.print_trace_domain_field) {
struct bt_value *domain_str;
- domain_str = bt_trace_borrow_environment_field_value_by_name(
+ domain_str = bt_trace_borrow_environment_entry_value_by_name(
trace_class, "domain");
if (domain_str) {
const char *str;
if (pretty->options.print_trace_procname_field) {
struct bt_value *procname_str;
- procname_str = bt_trace_borrow_environment_field_value_by_name(
+ procname_str = bt_trace_borrow_environment_entry_value_by_name(
trace_class, "procname");
if (procname_str) {
const char *str;
if (pretty->options.print_trace_vpid_field) {
struct bt_value *vpid_value;
- vpid_value = bt_trace_borrow_environment_field_value_by_name(
+ vpid_value = bt_trace_borrow_environment_entry_value_by_name(
trace_class, "vpid");
if (vpid_value) {
int64_t value;
enum bt_event_class_log_level log_level;
const char *log_level_str = NULL;
- log_level = bt_event_class_get_log_level(event_class);
- BT_ASSERT(log_level != BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN);
- if (log_level != BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
+ prop_avail = bt_event_class_get_log_level(event_class,
+ &log_level);
+ if (prop_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) {
log_level_str = log_level_names[log_level];
- }
+ BT_ASSERT(log_level_str);
- if (log_level_str) {
if (!pretty->start_line) {
g_string_append(pretty->string, ", ");
}
struct bt_field *field)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- struct bt_field_type *field_type = NULL;
- enum bt_integer_base base;
- enum bt_string_encoding encoding;
- int signedness;
+ enum bt_field_type_integer_preferred_display_base base;
struct bt_field_type *int_ft;
union {
uint64_t u;
bool rst_color = false;
enum bt_field_type_id ft_id;
- field_type = bt_field_borrow_type(field);
- if (!field_type) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
+ int_ft = bt_field_borrow_type(field);
+ BT_ASSERT(int_ft);
ft_id = bt_field_get_type_id(field);
-
- switch (ft_id) {
- case BT_FIELD_TYPE_ID_INTEGER:
- int_ft = field_type;
- break;
- case BT_FIELD_TYPE_ID_ENUM:
- int_ft = bt_field_type_enumeration_borrow_container_field_type(
- field_type);
- break;
- default:
- abort();
- }
-
- signedness = bt_field_type_integer_is_signed(int_ft);
- if (signedness < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- if (!signedness) {
- ret = bt_field_integer_unsigned_get_value(field, &v.u);
+ if (ft_id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER ||
+ ft_id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION) {
+ v.u = bt_field_unsigned_integer_get_value(field);
} else {
- ret = bt_field_integer_signed_get_value(field, &v.s);
- }
-
- if (ret < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- encoding = bt_field_type_integer_get_encoding(int_ft);
- switch (encoding) {
- case BT_STRING_ENCODING_UTF8:
- case BT_STRING_ENCODING_ASCII:
- g_string_append_c(pretty->tmp_string, (int) v.u);
- goto end;
- case BT_STRING_ENCODING_NONE:
- case BT_STRING_ENCODING_UNKNOWN:
- break;
- default:
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
+ v.s = bt_field_signed_integer_get_value(field);
}
if (pretty->use_colors) {
rst_color = true;
}
- base = bt_field_type_integer_get_base(int_ft);
+ base = bt_field_type_integer_get_preferred_display_base(int_ft);
switch (base) {
- case BT_INTEGER_BASE_BINARY:
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
{
int bitnr, len;
- len = bt_field_type_integer_get_size(int_ft);
- if (len < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ len = bt_field_type_integer_get_field_value_range(int_ft);
g_string_append(pretty->string, "0b");
v.u = _bt_piecewise_lshift(v.u, 64 - len);
for (bitnr = 0; bitnr < len; bitnr++) {
}
break;
}
- case BT_INTEGER_BASE_OCTAL:
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
{
- if (signedness) {
+ if (ft_id == BT_FIELD_TYPE_ID_SIGNED_INTEGER ||
+ ft_id == BT_FIELD_TYPE_ID_SIGNED_ENUMERATION) {
int len;
- len = bt_field_type_integer_get_size(int_ft);
- if (len < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ len = bt_field_type_integer_get_field_value_range(
+ int_ft);
if (len < 64) {
size_t rounded_len;
g_string_append_printf(pretty->string, "0%" PRIo64, v.u);
break;
}
- case BT_INTEGER_BASE_DECIMAL:
- case BT_INTEGER_BASE_UNSPECIFIED:
- if (!signedness) {
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL:
+ if (ft_id == BT_FIELD_TYPE_ID_UNSIGNED_INTEGER ||
+ ft_id == BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION) {
g_string_append_printf(pretty->string, "%" PRIu64, v.u);
} else {
g_string_append_printf(pretty->string, "%" PRId64, v.s);
}
break;
- case BT_INTEGER_BASE_HEXADECIMAL:
+ case BT_FIELD_TYPE_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
{
int len;
- len = bt_field_type_integer_get_size(int_ft);
- if (len < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ len = bt_field_type_integer_get_field_value_range(int_ft);
if (len < 64) {
/* Round length to the nearest nibble */
uint8_t rounded_len = ((len + 3) & ~0x3);
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field_type *enumeration_field_type = NULL;
- struct bt_field_type *container_field_type = NULL;
- struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
- int nr_mappings = 0;
+ bt_field_type_enumeration_mapping_label_array label_array;
+ uint64_t label_count;
+ uint64_t i;
enumeration_field_type = bt_field_borrow_type(field);
if (!enumeration_field_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- container_field_type =
- bt_field_type_enumeration_borrow_container_field_type(
- enumeration_field_type);
- if (!container_field_type) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
+
+ switch (bt_field_get_type_id(field)) {
+ case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION:
+ ret = bt_field_unsigned_enumeration_get_mapping_labels(field,
+ &label_array, &label_count);
+ break;
+ case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION:
+ ret = bt_field_signed_enumeration_get_mapping_labels(field,
+ &label_array, &label_count);
+ break;
+ default:
+ abort();
}
- iter = bt_field_enumeration_get_mappings(field);
- if (!iter) {
+
+ if (ret) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
+
g_string_append(pretty->string, "( ");
- ret = bt_field_type_enumeration_mapping_iterator_next(iter);
- if (ret) {
+ if (label_count == 0) {
if (pretty->use_colors) {
g_string_append(pretty->string, COLOR_UNKNOWN);
}
}
goto skip_loop;
}
- for (;;) {
- const char *mapping_name;
+ for (i = 0; i < label_count; i++) {
+ const char *mapping_name = label_array[i];
- if (bt_field_type_enumeration_mapping_iterator_signed_get(
- iter, &mapping_name, NULL, NULL) < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- if (nr_mappings++)
+ if (i == 0) {
g_string_append(pretty->string, ", ");
+ }
if (pretty->use_colors) {
g_string_append(pretty->string, COLOR_ENUM_MAPPING_NAME);
}
if (pretty->use_colors) {
g_string_append(pretty->string, COLOR_RST);
}
- if (bt_field_type_enumeration_mapping_iterator_next(iter) < 0) {
- break;
- }
}
skip_loop:
g_string_append(pretty->string, " : container = ");
}
g_string_append(pretty->string, " )");
end:
- bt_put(iter);
return ret;
}
enum bt_component_status print_struct_field(struct pretty_component *pretty,
struct bt_field *_struct,
struct bt_field_type *struct_type,
- int i, bool print_names, int *nr_printed_fields,
+ uint64_t i, bool print_names, uint64_t *nr_printed_fields,
GQuark *filter_fields, int filter_array_len)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *field = NULL;
struct bt_field_type *field_type = NULL;;
- field = bt_field_structure_borrow_field_by_index(_struct, i);
+ field = bt_field_structure_borrow_member_field_by_index(_struct, i);
if (!field) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- if (bt_field_type_structure_borrow_field_by_index(struct_type,
- &field_name, &field_type, i) < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+
+ bt_field_type_structure_borrow_member_by_index(struct_type, i,
+ &field_name, &field_type);
if (filter_fields && !filter_field_name(pretty, field_name,
filter_fields, filter_array_len)) {
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field_type *struct_type = NULL;
- int nr_fields, i, nr_printed_fields;
+ uint64_t nr_fields, i, nr_printed_fields;
struct_type = bt_field_borrow_type(_struct);
if (!struct_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- nr_fields = bt_field_type_structure_get_field_count(struct_type);
+ nr_fields = bt_field_type_structure_get_member_count(struct_type);
if (nr_fields < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
static
enum bt_component_status print_array_field(struct pretty_component *pretty,
- struct bt_field *array, uint64_t i,
- bool is_string, bool print_names)
+ struct bt_field *array, uint64_t i, bool print_names)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *field = NULL;
- if (!is_string) {
- if (i != 0) {
- g_string_append(pretty->string, ", ");
- } else {
- g_string_append(pretty->string, " ");
- }
- if (print_names) {
- g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
- }
+ if (i != 0) {
+ g_string_append(pretty->string, ", ");
+ } else {
+ g_string_append(pretty->string, " ");
}
- field = bt_field_array_borrow_field(array, i);
- if (!field) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
+ if (print_names) {
+ g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
}
- ret = print_field(pretty, field, print_names, NULL, 0);
-end:
- return ret;
+ field = bt_field_array_borrow_element_field_by_index(array, i);
+ BT_ASSERT(field);
+ return print_field(pretty, field, print_names, NULL, 0);
}
static
struct bt_field *array, bool print_names)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- struct bt_field_type *array_type = NULL, *field_type = NULL;
- enum bt_field_type_id type_id;
- int64_t len;
+ struct bt_field_type *array_type = NULL;
+ uint64_t len;
uint64_t i;
- bool is_string = false;
array_type = bt_field_borrow_type(array);
if (!array_type) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- field_type = bt_field_type_array_borrow_element_field_type(array_type);
- if (!field_type) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- len = bt_field_type_array_get_length(array_type);
- if (len < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- type_id = bt_field_type_get_type_id(field_type);
- if (type_id == BT_FIELD_TYPE_ID_INTEGER) {
- enum bt_string_encoding encoding;
-
- encoding = bt_field_type_integer_get_encoding(field_type);
- if (encoding == BT_STRING_ENCODING_UTF8
- || encoding == BT_STRING_ENCODING_ASCII) {
- int integer_len, integer_alignment;
-
- integer_len = bt_field_type_integer_get_size(field_type);
- if (integer_len < 0) {
- return BT_COMPONENT_STATUS_ERROR;
- }
- integer_alignment = bt_field_type_get_alignment(field_type);
- if (integer_alignment < 0) {
- return BT_COMPONENT_STATUS_ERROR;
- }
- if (integer_len == CHAR_BIT
- && integer_alignment == CHAR_BIT) {
- is_string = true;
- }
- }
- }
-
- if (is_string) {
- g_string_assign(pretty->tmp_string, "");
- } else {
- g_string_append(pretty->string, "[");
- }
-
+ len = bt_field_array_get_length(array);
+ g_string_append(pretty->string, "[");
pretty->depth++;
for (i = 0; i < len; i++) {
- ret = print_array_field(pretty, array, i, is_string, print_names);
+ ret = print_array_field(pretty, array, i, print_names);
if (ret != BT_COMPONENT_STATUS_OK) {
goto end;
}
}
pretty->depth--;
-
- if (is_string) {
- if (pretty->use_colors) {
- g_string_append(pretty->string, COLOR_STRING_VALUE);
- }
- print_escape_string(pretty, pretty->tmp_string->str);
- if (pretty->use_colors) {
- g_string_append(pretty->string, COLOR_RST);
- }
- } else {
- g_string_append(pretty->string, " ]");
- }
+ g_string_append(pretty->string, " ]");
end:
return ret;
static
enum bt_component_status print_sequence_field(struct pretty_component *pretty,
- struct bt_field *seq, uint64_t i,
- bool is_string, bool print_names)
+ struct bt_field *seq, uint64_t i, bool print_names)
{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *field = NULL;
- if (!is_string) {
- if (i != 0) {
- g_string_append(pretty->string, ", ");
- } else {
- g_string_append(pretty->string, " ");
- }
- if (print_names) {
- g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
- }
+ if (i != 0) {
+ g_string_append(pretty->string, ", ");
+ } else {
+ g_string_append(pretty->string, " ");
}
- field = bt_field_sequence_borrow_field(seq, i);
- if (!field) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
+ if (print_names) {
+ g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
}
- ret = print_field(pretty, field, print_names, NULL, 0);
-end:
- return ret;
+ field = bt_field_array_borrow_element_field_by_index(seq, i);
+ BT_ASSERT(field);
+ return print_field(pretty, field, print_names, NULL, 0);
}
static
struct bt_field *seq, bool print_names)
{
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- struct bt_field_type *seq_type = NULL, *field_type = NULL;
- enum bt_field_type_id type_id;
- int64_t len;
+ uint64_t len;
uint64_t i;
- bool is_string = false;
- seq_type = bt_field_borrow_type(seq);
- if (!seq_type) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- len = bt_field_sequence_get_length(seq);
+ len = bt_field_array_get_length(seq);
if (len < 0) {
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- field_type = bt_field_type_sequence_borrow_element_field_type(seq_type);
- if (!field_type) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- type_id = bt_field_type_get_type_id(field_type);
- if (type_id == BT_FIELD_TYPE_ID_INTEGER) {
- enum bt_string_encoding encoding;
-
- encoding = bt_field_type_integer_get_encoding(field_type);
- if (encoding == BT_STRING_ENCODING_UTF8
- || encoding == BT_STRING_ENCODING_ASCII) {
- int integer_len, integer_alignment;
- integer_len = bt_field_type_integer_get_size(field_type);
- if (integer_len < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- integer_alignment = bt_field_type_get_alignment(field_type);
- if (integer_alignment < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- if (integer_len == CHAR_BIT
- && integer_alignment == CHAR_BIT) {
- is_string = true;
- }
- }
- }
-
- if (is_string) {
- g_string_assign(pretty->tmp_string, "");
- } else {
- g_string_append(pretty->string, "[");
- }
+ g_string_append(pretty->string, "[");
pretty->depth++;
for (i = 0; i < len; i++) {
- ret = print_sequence_field(pretty, seq, i,
- is_string, print_names);
+ ret = print_sequence_field(pretty, seq, i, print_names);
if (ret != BT_COMPONENT_STATUS_OK) {
goto end;
}
}
pretty->depth--;
-
- if (is_string) {
- if (pretty->use_colors) {
- g_string_append(pretty->string, COLOR_STRING_VALUE);
- }
- print_escape_string(pretty, pretty->tmp_string->str);
- if (pretty->use_colors) {
- g_string_append(pretty->string, COLOR_RST);
- }
- } else {
- g_string_append(pretty->string, " ]");
- }
+ g_string_append(pretty->string, " ]");
end:
return ret;
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *field = NULL;
- field = bt_field_variant_borrow_current_field(variant);
- if (!field) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
+ field = bt_field_variant_borrow_selected_option_field(variant);
+ BT_ASSERT(field);
g_string_append(pretty->string, "{ ");
pretty->depth++;
if (print_names) {
- int iret;
- struct bt_field_type *var_ft;
- struct bt_field_type *tag_ft;
- struct bt_field_type *container_ft;
- const char *tag_choice;
- bt_bool is_signed;
- struct bt_field_type_enumeration_mapping_iterator *iter;
-
- var_ft = bt_field_borrow_type(variant);
- tag_ft = bt_field_type_variant_borrow_tag_field_type(
- var_ft);
- container_ft =
- bt_field_type_enumeration_borrow_container_field_type(
- tag_ft);
- is_signed = bt_field_type_integer_is_signed(container_ft);
-
- if (is_signed) {
- int64_t tag;
-
- iret = bt_field_variant_get_tag_signed(variant, &tag);
- if (iret) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- iter = bt_field_type_enumeration_signed_find_mappings_by_value(
- tag_ft, tag);
- } else {
- uint64_t tag;
-
- iret = bt_field_variant_get_tag_unsigned(variant, &tag);
- if (iret) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- iter = bt_field_type_enumeration_unsigned_find_mappings_by_value(
- tag_ft, tag);
- }
-
- if (!iter) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- iret = bt_field_type_enumeration_mapping_iterator_next(
- iter);
- if (!iter || ret) {
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
-
- iret =
- bt_field_type_enumeration_mapping_iterator_signed_get(
- iter, &tag_choice, NULL, NULL);
- if (iret) {
- bt_put(iter);
- ret = BT_COMPONENT_STATUS_ERROR;
- goto end;
- }
- print_field_name_equal(pretty, tag_choice);
- bt_put(iter);
+ // TODO: find tag's name using field path
+ // print_field_name_equal(pretty, tag_choice);
}
ret = print_field(pretty, field, print_names, NULL, 0);
if (ret != BT_COMPONENT_STATUS_OK) {
type_id = bt_field_get_type_id(field);
switch (type_id) {
- case BT_FIELD_TYPE_ID_INTEGER:
+ case BT_FIELD_TYPE_ID_UNSIGNED_INTEGER:
+ case BT_FIELD_TYPE_ID_SIGNED_INTEGER:
return print_integer(pretty, field);
- case BT_FIELD_TYPE_ID_FLOAT:
+ case BT_FIELD_TYPE_ID_REAL:
{
double v;
- if (bt_field_floating_point_get_value(field, &v)) {
- return BT_COMPONENT_STATUS_ERROR;
- }
+ v = bt_field_real_get_value(field);
if (pretty->use_colors) {
g_string_append(pretty->string, COLOR_NUMBER_VALUE);
}
}
return BT_COMPONENT_STATUS_OK;
}
- case BT_FIELD_TYPE_ID_ENUM:
+ case BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION:
+ case BT_FIELD_TYPE_ID_SIGNED_ENUMERATION:
return print_enum(pretty, field);
case BT_FIELD_TYPE_ID_STRING:
{
}
return BT_COMPONENT_STATUS_OK;
}
- case BT_FIELD_TYPE_ID_STRUCT:
+ case BT_FIELD_TYPE_ID_STRUCTURE:
return print_struct(pretty, field, print_names, filter_fields,
filter_array_len);
case BT_FIELD_TYPE_ID_VARIANT:
return print_variant(pretty, field, print_names);
- case BT_FIELD_TYPE_ID_ARRAY:
+ case BT_FIELD_TYPE_ID_STATIC_ARRAY:
return print_array(pretty, field, print_names);
- case BT_FIELD_TYPE_ID_SEQUENCE:
+ case BT_FIELD_TYPE_ID_DYNAMIC_ARRAY:
return print_sequence(pretty, field, print_names);
default:
// TODO: log instead
ret = BT_COMPONENT_STATUS_ERROR;
goto end;
}
- main_field = bt_packet_borrow_context(packet);
+ main_field = bt_packet_borrow_context_field(packet);
if (!main_field) {
goto end;
}
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *main_field = NULL;
- main_field = bt_event_borrow_header(event);
+ main_field = bt_event_borrow_header_field(event);
if (!main_field) {
goto end;
}
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *main_field = NULL;
- main_field = bt_event_borrow_stream_event_context(event);
+ main_field = bt_event_borrow_common_context_field(event);
if (!main_field) {
goto end;
}
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *main_field = NULL;
- main_field = bt_event_borrow_context(event);
+ main_field = bt_event_borrow_specific_context_field(event);
if (!main_field) {
goto end;
}
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_field *main_field = NULL;
- main_field = bt_event_borrow_payload(event);
+ main_field = bt_event_borrow_payload_field(event);
if (!main_field) {
goto end;
}
struct pretty_component *pretty, struct bt_packet *packet,
uint64_t count, const char *elem_type)
{
+#if 0
enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
struct bt_stream *stream = NULL;
struct bt_stream_class *stream_class = NULL;
}
return ret;
+#endif
+ return 0;
}
BT_HIDDEN
enum bt_component_status pretty_print_packet(struct pretty_component *pretty,
struct bt_notification *packet_beginning_notif)
{
+#if 0
struct bt_packet *packet = bt_notification_packet_begin_borrow_packet(
packet_beginning_notif);
uint64_t count;
end:
return status;
+#endif
+ return 0;
}
int ret = 0;
const unsigned char *cc_uuid;
const char *cc_name;
+ enum bt_clock_value_status cv_status = BT_CLOCK_VALUE_STATUS_KNOWN;
BT_ASSERT(notif);
BT_ASSERT(ts_ns);
case BT_NOTIFICATION_TYPE_EVENT:
event = bt_notification_event_borrow_event(notif);
BT_ASSERT(event);
- clock_value = bt_event_borrow_default_clock_value(event);
+ cv_status = bt_event_borrow_default_clock_value(event,
+ &clock_value);
break;
case BT_NOTIFICATION_TYPE_INACTIVITY:
goto end;
}
+ if (cv_status != BT_CLOCK_VALUE_STATUS_KNOWN) {
+ BT_LOGE_STR("Unsupported unknown clock value.");
+ ret = -1;
+ goto end;
+ }
+
/*
* If the clock value is missing, then we consider that this
* notification has no time. In this case it's always the
goto end;
}
- clock_class = bt_clock_value_borrow_class(clock_value);
+ clock_class = bt_clock_value_borrow_clock_class(clock_value);
BT_ASSERT(clock_class);
cc_uuid = bt_clock_class_get_uuid(clock_class);
cc_name = bt_clock_class_get_name(clock_class);
}
}
- ret = bt_clock_value_get_value_ns_from_epoch(clock_value, ts_ns);
+ ret = bt_clock_value_get_ns_from_origin(clock_value, ts_ns);
if (ret) {
BT_LOGE("Cannot get nanoseconds from Epoch of clock value: "
"clock-value-addr=%p", clock_value);
test_ctf_ir_ref_LDADD = $(COMMON_TEST_LDADD)
-test_bt_ctf_field_type_validation_LDADD = $(COMMON_TEST_LDADD)
-
-test_ir_visit_LDADD = $(COMMON_TEST_LDADD)
-
test_graph_topo_LDADD = $(COMMON_TEST_LDADD)
test_bt_notification_iterator_LDADD = $(COMMON_TEST_LDADD)
noinst_PROGRAMS = test_bitfield test_ctf_writer test_bt_values \
- test_ctf_ir_ref test_bt_ctf_field_type_validation test_ir_visit \
- test_graph_topo test_bt_notification_iterator
+ test_ctf_ir_ref test_graph_topo test_bt_notification_iterator
test_bitfield_SOURCES = test_bitfield.c
test_ctf_writer_SOURCES = test_ctf_writer.c
test_bt_values_SOURCES = test_bt_values.c
test_ctf_ir_ref_SOURCES = test_ctf_ir_ref.c
-test_bt_ctf_field_type_validation_SOURCES = test_bt_ctf_field_type_validation.c
-test_ir_visit_SOURCES = test_ir_visit.c
test_graph_topo_SOURCES = test_graph_topo.c
test_bt_notification_iterator_SOURCES = test_bt_notification_iterator.c
+++ /dev/null
-/*
- * test_bt_field_type_validation.c
- *
- * Babeltrace CTF IR field type validation test
- *
- * Copyright (c) 2016 Philippe Proulx <pproulx@efficios.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/field-path.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/event-class.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/assert-internal.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdarg.h>
-#include <glib.h>
-#include "tap/tap.h"
-
-static
-struct bt_field_type *get_good_packet_header_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- magic:
- class: int
- size: 32
- uuid:
- class: array
- length: 16
- element-type:
- class: int
- size: 8
- stream_id:
- class: int
- size: 32
- iron:
- class: struct
- fields:
- listen:
- class: string
- dust:
- class: int
- size: 23
- parallel:
- class: enum
- value-type:
- class: int
- size: 10
- members:
- - RED
- - BLUE
- - YELLOW
- fire:
- class: struct
- fields:
- word:
- class: int
- size: 17
- rabbit:
- class: string
- keen:
- class: array
- length: word
- element-type:
- class: variant
- tag: iron.parallel
- types:
- RED:
- class: string
- BLUE:
- class: array
- length: magic
- element-type:
- class: int
- size: 5
- YELLOW:
- class: struct
- report:
- class: array
- length: trace.packet.header.iron.dust
- element-type:
- class: string
- group:
- class: array
- length: trace.packet.header.stream_id
- element-type:
- class: string
- serious:
- class: int
- size: 1
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_magic = NULL;
- struct bt_field_type *root_uuid = NULL;
- struct bt_field_type *root_uuid_elem = NULL;
- struct bt_field_type *root_stream_id = NULL;
- struct bt_field_type *root_iron = NULL;
- struct bt_field_type *root_iron_listen = NULL;
- struct bt_field_type *root_iron_dust = NULL;
- struct bt_field_type *root_iron_parallel = NULL;
- struct bt_field_type *root_iron_parallel_int = NULL;
- struct bt_field_type *root_iron_fire = NULL;
- struct bt_field_type *root_iron_fire_word = NULL;
- struct bt_field_type *root_iron_fire_rabbit = NULL;
- struct bt_field_type *root_iron_fire_keen = NULL;
- struct bt_field_type *root_iron_fire_keen_elem = NULL;
- struct bt_field_type *root_iron_fire_keen_elem_RED = NULL;
- struct bt_field_type *root_iron_fire_keen_elem_BLUE = NULL;
- struct bt_field_type *root_iron_fire_keen_elem_BLUE_elem = NULL;
- struct bt_field_type *root_iron_fire_keen_elem_YELLOW = NULL;
- struct bt_field_type *root_iron_report = NULL;
- struct bt_field_type *root_iron_report_elem = NULL;
- struct bt_field_type *root_iron_group = NULL;
- struct bt_field_type *root_iron_group_elem = NULL;
- struct bt_field_type *root_serious = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_magic = bt_field_type_integer_create(32);
- BT_ASSERT(root_magic);
- ret = bt_field_type_integer_set_is_signed(root_magic, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_magic, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_magic, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_magic, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_magic, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_magic, "magic");
- BT_ASSERT(ret == 0);
- root_uuid_elem = bt_field_type_integer_create(8);
- BT_ASSERT(root_uuid_elem);
- ret = bt_field_type_integer_set_is_signed(root_uuid_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_uuid_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_uuid_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_uuid_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_uuid_elem, 8);
- BT_ASSERT(ret == 0);
- root_uuid = bt_field_type_array_create(root_uuid_elem, 16);
- BT_ASSERT(root_uuid);
- ret = bt_field_type_structure_add_field(root, root_uuid, "uuid");
- BT_ASSERT(ret == 0);
- root_stream_id = bt_field_type_integer_create(32);
- BT_ASSERT(root_stream_id);
- ret = bt_field_type_integer_set_is_signed(root_stream_id, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_stream_id, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_stream_id, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_stream_id, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_stream_id, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_stream_id, "stream_id");
- BT_ASSERT(ret == 0);
- root_iron = bt_field_type_structure_create();
- BT_ASSERT(root_iron);
- ret = bt_field_type_set_alignment(root_iron, 8);
- BT_ASSERT(ret == 0);
- root_iron_listen = bt_field_type_string_create();
- BT_ASSERT(root_iron_listen);
- ret = bt_field_type_string_set_encoding(root_iron_listen, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_listen, "listen");
- BT_ASSERT(ret == 0);
- root_iron_dust = bt_field_type_integer_create(23);
- BT_ASSERT(root_iron_dust);
- ret = bt_field_type_integer_set_is_signed(root_iron_dust, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_iron_dust, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_iron_dust, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_iron_dust, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_iron_dust, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_dust, "dust");
- BT_ASSERT(ret == 0);
- root_iron_parallel_int = bt_field_type_integer_create(10);
- BT_ASSERT(root_iron_parallel_int);
- ret = bt_field_type_integer_set_is_signed(root_iron_parallel_int, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_iron_parallel_int, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_iron_parallel_int, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_iron_parallel_int, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_iron_parallel_int, 1);
- BT_ASSERT(ret == 0);
- root_iron_parallel = bt_field_type_enumeration_create(root_iron_parallel_int);
- BT_ASSERT(root_iron_parallel);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "RED", 0, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "BLUE", 1, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "YELLOW", 2, 2);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_parallel, "parallel");
- BT_ASSERT(ret == 0);
- root_iron_fire = bt_field_type_structure_create();
- BT_ASSERT(root_iron_fire);
- ret = bt_field_type_set_alignment(root_iron_fire, 8);
- BT_ASSERT(ret == 0);
- root_iron_fire_word = bt_field_type_integer_create(17);
- BT_ASSERT(root_iron_fire_word);
- ret = bt_field_type_integer_set_is_signed(root_iron_fire_word, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_iron_fire_word, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_iron_fire_word, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_iron_fire_word, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_iron_fire_word, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron_fire, root_iron_fire_word, "word");
- BT_ASSERT(ret == 0);
- root_iron_fire_rabbit = bt_field_type_string_create();
- BT_ASSERT(root_iron_fire_rabbit);
- ret = bt_field_type_string_set_encoding(root_iron_fire_rabbit, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron_fire, root_iron_fire_rabbit, "rabbit");
- BT_ASSERT(ret == 0);
- root_iron_fire_keen_elem = bt_field_type_variant_create(NULL, "iron.parallel");
- BT_ASSERT(root_iron_fire_keen_elem);
- root_iron_fire_keen_elem_RED = bt_field_type_string_create();
- BT_ASSERT(root_iron_fire_keen_elem_RED);
- ret = bt_field_type_string_set_encoding(root_iron_fire_keen_elem_RED, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_iron_fire_keen_elem, root_iron_fire_keen_elem_RED, "RED");
- BT_ASSERT(ret == 0);
- root_iron_fire_keen_elem_BLUE_elem = bt_field_type_integer_create(5);
- BT_ASSERT(root_iron_fire_keen_elem_BLUE_elem);
- ret = bt_field_type_integer_set_is_signed(root_iron_fire_keen_elem_BLUE_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_iron_fire_keen_elem_BLUE_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_iron_fire_keen_elem_BLUE_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_iron_fire_keen_elem_BLUE_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_iron_fire_keen_elem_BLUE_elem, 1);
- BT_ASSERT(ret == 0);
- root_iron_fire_keen_elem_BLUE = bt_field_type_sequence_create(root_iron_fire_keen_elem_BLUE_elem, "magic");
- BT_ASSERT(root_iron_fire_keen_elem_BLUE);
- ret = bt_field_type_variant_add_field(root_iron_fire_keen_elem, root_iron_fire_keen_elem_BLUE, "BLUE");
- BT_ASSERT(ret == 0);
- root_iron_fire_keen_elem_YELLOW = bt_field_type_structure_create();
- BT_ASSERT(root_iron_fire_keen_elem_YELLOW);
- ret = bt_field_type_set_alignment(root_iron_fire_keen_elem_YELLOW, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_iron_fire_keen_elem, root_iron_fire_keen_elem_YELLOW, "YELLOW");
- BT_ASSERT(ret == 0);
- root_iron_fire_keen = bt_field_type_sequence_create(root_iron_fire_keen_elem, "word");
- BT_ASSERT(root_iron_fire_keen);
- ret = bt_field_type_structure_add_field(root_iron_fire, root_iron_fire_keen, "keen");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_fire, "fire");
- BT_ASSERT(ret == 0);
- root_iron_report_elem = bt_field_type_string_create();
- BT_ASSERT(root_iron_report_elem);
- ret = bt_field_type_string_set_encoding(root_iron_report_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_iron_report = bt_field_type_sequence_create(root_iron_report_elem, "trace.packet.header.iron.dust");
- BT_ASSERT(root_iron_report);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_report, "report");
- BT_ASSERT(ret == 0);
- root_iron_group_elem = bt_field_type_string_create();
- BT_ASSERT(root_iron_group_elem);
- ret = bt_field_type_string_set_encoding(root_iron_group_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_iron_group = bt_field_type_sequence_create(root_iron_group_elem, "trace.packet.header.stream_id");
- BT_ASSERT(root_iron_group);
- ret = bt_field_type_structure_add_field(root_iron, root_iron_group, "group");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_iron, "iron");
- BT_ASSERT(ret == 0);
- root_serious = bt_field_type_integer_create(1);
- BT_ASSERT(root_serious);
- ret = bt_field_type_integer_set_is_signed(root_serious, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_serious, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_serious, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_serious, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_serious, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_serious, "serious");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_magic);
- BT_PUT(root_uuid);
- BT_PUT(root_uuid_elem);
- BT_PUT(root_stream_id);
- BT_PUT(root_iron);
- BT_PUT(root_iron_listen);
- BT_PUT(root_iron_dust);
- BT_PUT(root_iron_parallel);
- BT_PUT(root_iron_parallel_int);
- BT_PUT(root_iron_fire);
- BT_PUT(root_iron_fire_word);
- BT_PUT(root_iron_fire_rabbit);
- BT_PUT(root_iron_fire_keen);
- BT_PUT(root_iron_fire_keen_elem);
- BT_PUT(root_iron_fire_keen_elem_RED);
- BT_PUT(root_iron_fire_keen_elem_BLUE);
- BT_PUT(root_iron_fire_keen_elem_BLUE_elem);
- BT_PUT(root_iron_fire_keen_elem_YELLOW);
- BT_PUT(root_iron_report);
- BT_PUT(root_iron_report_elem);
- BT_PUT(root_iron_group);
- BT_PUT(root_iron_group_elem);
- BT_PUT(root_serious);
-
- return root;
-}
-
-static
-struct bt_field_type *get_good_packet_context_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- placid:
- class: int
- size: 32
- meow:
- class: string
- serious:
- class: int
- size: 11
- naive:
- class: array
- length: 17
- element-type:
- class: array
- length: placid
- element-type:
- class: string
- clover:
- class: struct
- fields:
- oval:
- class: int
- size: 17
- whole:
- class: variant
- tag: iron.parallel
- types:
- BLUE:
- class: array
- length: trace.packet.header.iron.fire.word
- element-type:
- class: string
- RED:
- class: int
- size: 44
- YELLOW:
- class: string
- egg:
- class: array
- length: stream.packet.context.clover.oval
- element-type:
- class: int
- size: 55
- square:
- class: enum
- value-type:
- class: int
- size: 12
- members:
- - YOUNG
- - OLD
- useful:
- class: array
- length: serious
- element-type:
- class: int
- size: 2
- tart:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_placid = NULL;
- struct bt_field_type *root_meow = NULL;
- struct bt_field_type *root_serious = NULL;
- struct bt_field_type *root_naive = NULL;
- struct bt_field_type *root_naive_elem = NULL;
- struct bt_field_type *root_naive_elem_elem = NULL;
- struct bt_field_type *root_clover = NULL;
- struct bt_field_type *root_clover_oval = NULL;
- struct bt_field_type *root_clover_whole = NULL;
- struct bt_field_type *root_clover_whole_BLUE = NULL;
- struct bt_field_type *root_clover_whole_BLUE_elem = NULL;
- struct bt_field_type *root_clover_whole_RED = NULL;
- struct bt_field_type *root_clover_whole_YELLOW = NULL;
- struct bt_field_type *root_clover_egg = NULL;
- struct bt_field_type *root_clover_egg_elem = NULL;
- struct bt_field_type *root_clover_square = NULL;
- struct bt_field_type *root_clover_square_int = NULL;
- struct bt_field_type *root_clover_useful = NULL;
- struct bt_field_type *root_clover_useful_elem = NULL;
- struct bt_field_type *root_tart = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_placid = bt_field_type_integer_create(32);
- BT_ASSERT(root_placid);
- ret = bt_field_type_integer_set_is_signed(root_placid, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_placid, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_placid, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_placid, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_placid, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_placid, "placid");
- BT_ASSERT(ret == 0);
- root_meow = bt_field_type_string_create();
- BT_ASSERT(root_meow);
- ret = bt_field_type_string_set_encoding(root_meow, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_meow, "meow");
- BT_ASSERT(ret == 0);
- root_serious = bt_field_type_integer_create(11);
- BT_ASSERT(root_serious);
- ret = bt_field_type_integer_set_is_signed(root_serious, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_serious, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_serious, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_serious, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_serious, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_serious, "serious");
- BT_ASSERT(ret == 0);
- root_naive_elem_elem = bt_field_type_string_create();
- BT_ASSERT(root_naive_elem_elem);
- ret = bt_field_type_string_set_encoding(root_naive_elem_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_naive_elem = bt_field_type_sequence_create(root_naive_elem_elem, "placid");
- BT_ASSERT(root_naive_elem);
- root_naive = bt_field_type_array_create(root_naive_elem, 17);
- BT_ASSERT(root_naive);
- ret = bt_field_type_structure_add_field(root, root_naive, "naive");
- BT_ASSERT(ret == 0);
- root_clover = bt_field_type_structure_create();
- BT_ASSERT(root_clover);
- ret = bt_field_type_set_alignment(root_clover, 1);
- BT_ASSERT(ret == 0);
- root_clover_oval = bt_field_type_integer_create(17);
- BT_ASSERT(root_clover_oval);
- ret = bt_field_type_integer_set_is_signed(root_clover_oval, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_clover_oval, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_clover_oval, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_clover_oval, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_clover_oval, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_clover, root_clover_oval, "oval");
- BT_ASSERT(ret == 0);
- root_clover_whole = bt_field_type_variant_create(NULL, "iron.parallel");
- BT_ASSERT(root_clover_whole);
- root_clover_whole_BLUE_elem = bt_field_type_string_create();
- BT_ASSERT(root_clover_whole_BLUE_elem);
- ret = bt_field_type_string_set_encoding(root_clover_whole_BLUE_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_clover_whole_BLUE = bt_field_type_sequence_create(root_clover_whole_BLUE_elem, "trace.packet.header.iron.fire.word");
- BT_ASSERT(root_clover_whole_BLUE);
- ret = bt_field_type_variant_add_field(root_clover_whole, root_clover_whole_BLUE, "BLUE");
- BT_ASSERT(ret == 0);
- root_clover_whole_RED = bt_field_type_integer_create(44);
- BT_ASSERT(root_clover_whole_RED);
- ret = bt_field_type_integer_set_is_signed(root_clover_whole_RED, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_clover_whole_RED, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_clover_whole_RED, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_clover_whole_RED, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_clover_whole_RED, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_clover_whole, root_clover_whole_RED, "RED");
- BT_ASSERT(ret == 0);
- root_clover_whole_YELLOW = bt_field_type_string_create();
- BT_ASSERT(root_clover_whole_YELLOW);
- ret = bt_field_type_string_set_encoding(root_clover_whole_YELLOW, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_clover_whole, root_clover_whole_YELLOW, "YELLOW");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_clover, root_clover_whole, "whole");
- BT_ASSERT(ret == 0);
- root_clover_egg_elem = bt_field_type_integer_create(55);
- BT_ASSERT(root_clover_egg_elem);
- ret = bt_field_type_integer_set_is_signed(root_clover_egg_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_clover_egg_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_clover_egg_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_clover_egg_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_clover_egg_elem, 1);
- BT_ASSERT(ret == 0);
- root_clover_egg = bt_field_type_sequence_create(root_clover_egg_elem, "stream.packet.context.clover.oval");
- BT_ASSERT(root_clover_egg);
- ret = bt_field_type_structure_add_field(root_clover, root_clover_egg, "egg");
- BT_ASSERT(ret == 0);
- root_clover_square_int = bt_field_type_integer_create(12);
- BT_ASSERT(root_clover_square_int);
- ret = bt_field_type_integer_set_is_signed(root_clover_square_int, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_clover_square_int, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_clover_square_int, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_clover_square_int, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_clover_square_int, 1);
- BT_ASSERT(ret == 0);
- root_clover_square = bt_field_type_enumeration_create(root_clover_square_int);
- BT_ASSERT(root_clover_square);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_clover_square, "YOUNG", 0, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_clover_square, "OLD", 1, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_clover, root_clover_square, "square");
- BT_ASSERT(ret == 0);
- root_clover_useful_elem = bt_field_type_integer_create(2);
- BT_ASSERT(root_clover_useful_elem);
- ret = bt_field_type_integer_set_is_signed(root_clover_useful_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_clover_useful_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_clover_useful_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_clover_useful_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_clover_useful_elem, 1);
- BT_ASSERT(ret == 0);
- root_clover_useful = bt_field_type_sequence_create(root_clover_useful_elem, "serious");
- BT_ASSERT(root_clover_useful);
- ret = bt_field_type_structure_add_field(root_clover, root_clover_useful, "useful");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_clover, "clover");
- BT_ASSERT(ret == 0);
- root_tart = bt_field_type_string_create();
- BT_ASSERT(root_tart);
- ret = bt_field_type_string_set_encoding(root_tart, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_tart, "tart");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_placid);
- BT_PUT(root_meow);
- BT_PUT(root_serious);
- BT_PUT(root_naive);
- BT_PUT(root_naive_elem);
- BT_PUT(root_naive_elem_elem);
- BT_PUT(root_clover);
- BT_PUT(root_clover_oval);
- BT_PUT(root_clover_whole);
- BT_PUT(root_clover_whole_BLUE);
- BT_PUT(root_clover_whole_BLUE_elem);
- BT_PUT(root_clover_whole_RED);
- BT_PUT(root_clover_whole_YELLOW);
- BT_PUT(root_clover_egg);
- BT_PUT(root_clover_egg_elem);
- BT_PUT(root_clover_square);
- BT_PUT(root_clover_square_int);
- BT_PUT(root_clover_useful);
- BT_PUT(root_clover_useful_elem);
- BT_PUT(root_tart);
-
- return root;
-}
-
-
-static
-struct bt_field_type *get_good_event_header_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- id:
- class: int
- size: 17
- timestamp:
- class: int
- size: 64
- action:
- class: struct
- fields:
- special:
- class: int
- size: 17
- lucky:
- class: array
- length: stream.packet.context.placid
- element-type:
- class: string
- dream:
- class: string
- grandiose:
- class: array
- length: trace.packet.header.serious
- element-type:
- class: int
- size: 3
- stiff:
- class: array
- length: clover.whole.RED
- element-type:
- class: string
- fruit:
- class: struct
- fields:
- apple:
- class: array
- length: action.special
- element-type:
- class: int
- size: 5
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_id = NULL;
- struct bt_field_type *root_timestamp = NULL;
- struct bt_field_type *root_action = NULL;
- struct bt_field_type *root_action_special = NULL;
- struct bt_field_type *root_action_lucky = NULL;
- struct bt_field_type *root_action_lucky_elem = NULL;
- struct bt_field_type *root_action_dream = NULL;
- struct bt_field_type *root_action_grandiose = NULL;
- struct bt_field_type *root_action_grandiose_elem = NULL;
- struct bt_field_type *root_stiff = NULL;
- struct bt_field_type *root_stiff_elem = NULL;
- struct bt_field_type *root_fruit = NULL;
- struct bt_field_type *root_fruit_apple = NULL;
- struct bt_field_type *root_fruit_apple_elem = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_id = bt_field_type_integer_create(17);
- BT_ASSERT(root_id);
- ret = bt_field_type_integer_set_is_signed(root_id, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_id, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_id, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_id, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_id, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_id, "id");
- BT_ASSERT(ret == 0);
- root_timestamp = bt_field_type_integer_create(64);
- BT_ASSERT(root_timestamp);
- ret = bt_field_type_integer_set_is_signed(root_timestamp, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_timestamp, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_timestamp, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_timestamp, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_timestamp, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_timestamp, "timestamp");
- BT_ASSERT(ret == 0);
- root_action = bt_field_type_structure_create();
- BT_ASSERT(root_action);
- ret = bt_field_type_set_alignment(root_action, 8);
- BT_ASSERT(ret == 0);
- root_action_special = bt_field_type_integer_create(17);
- BT_ASSERT(root_action_special);
- ret = bt_field_type_integer_set_is_signed(root_action_special, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_action_special, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_action_special, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_action_special, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_action_special, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_action, root_action_special, "special");
- BT_ASSERT(ret == 0);
- root_action_lucky_elem = bt_field_type_string_create();
- BT_ASSERT(root_action_lucky_elem);
- ret = bt_field_type_string_set_encoding(root_action_lucky_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_action_lucky = bt_field_type_sequence_create(root_action_lucky_elem, "stream.packet.context.placid");
- BT_ASSERT(root_action_lucky);
- ret = bt_field_type_structure_add_field(root_action, root_action_lucky, "lucky");
- BT_ASSERT(ret == 0);
- root_action_dream = bt_field_type_string_create();
- BT_ASSERT(root_action_dream);
- ret = bt_field_type_string_set_encoding(root_action_dream, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_action, root_action_dream, "dream");
- BT_ASSERT(ret == 0);
- root_action_grandiose_elem = bt_field_type_integer_create(3);
- BT_ASSERT(root_action_grandiose_elem);
- ret = bt_field_type_integer_set_is_signed(root_action_grandiose_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_action_grandiose_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_action_grandiose_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_action_grandiose_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_action_grandiose_elem, 1);
- BT_ASSERT(ret == 0);
- root_action_grandiose = bt_field_type_sequence_create(root_action_grandiose_elem, "trace.packet.header.serious");
- BT_ASSERT(root_action_grandiose);
- ret = bt_field_type_structure_add_field(root_action, root_action_grandiose, "grandiose");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_action, "action");
- BT_ASSERT(ret == 0);
- root_stiff_elem = bt_field_type_string_create();
- BT_ASSERT(root_stiff_elem);
- ret = bt_field_type_string_set_encoding(root_stiff_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_stiff = bt_field_type_sequence_create(root_stiff_elem, "clover.whole.RED");
- BT_ASSERT(root_stiff);
- ret = bt_field_type_structure_add_field(root, root_stiff, "stiff");
- BT_ASSERT(ret == 0);
- root_fruit = bt_field_type_structure_create();
- BT_ASSERT(root_fruit);
- ret = bt_field_type_set_alignment(root_fruit, 1);
- BT_ASSERT(ret == 0);
- root_fruit_apple_elem = bt_field_type_integer_create(5);
- BT_ASSERT(root_fruit_apple_elem);
- ret = bt_field_type_integer_set_is_signed(root_fruit_apple_elem, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_fruit_apple_elem, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_fruit_apple_elem, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_fruit_apple_elem, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_fruit_apple_elem, 1);
- BT_ASSERT(ret == 0);
- root_fruit_apple = bt_field_type_sequence_create(root_fruit_apple_elem, "action.special");
- BT_ASSERT(root_fruit_apple);
- ret = bt_field_type_structure_add_field(root_fruit, root_fruit_apple, "apple");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_fruit, "fruit");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_id);
- BT_PUT(root_timestamp);
- BT_PUT(root_action);
- BT_PUT(root_action_special);
- BT_PUT(root_action_lucky);
- BT_PUT(root_action_lucky_elem);
- BT_PUT(root_action_dream);
- BT_PUT(root_action_grandiose);
- BT_PUT(root_action_grandiose_elem);
- BT_PUT(root_stiff);
- BT_PUT(root_stiff_elem);
- BT_PUT(root_fruit);
- BT_PUT(root_fruit_apple);
- BT_PUT(root_fruit_apple_elem);
-
- return root;
-}
-
-static
-struct bt_field_type *get_good_stream_event_context_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- face:
- class: struct
- fields:
- branch:
- class: array
- length: serious
- element-type:
- class: string
- income:
- class: array
- length: magic
- element-type:
- class: string
- magic:
- class: int
- size: 23
- lucky:
- class: array
- length: magic
- element-type:
- class: string
- cats:
- class: int
- size: 5
- dream:
- class: array
- length: stream.packet.context.placid
- element-type:
- class: array
- length: trace.packet.header.iron.dust
- element-type:
- class: array
- length: stream.event.context.face.magic
- element-type:
- class: string
- stream_id:
- class: int
- size: 9
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_face = NULL;
- struct bt_field_type *root_face_branch = NULL;
- struct bt_field_type *root_face_branch_elem = NULL;
- struct bt_field_type *root_face_income = NULL;
- struct bt_field_type *root_face_income_elem = NULL;
- struct bt_field_type *root_face_magic = NULL;
- struct bt_field_type *root_face_lucky = NULL;
- struct bt_field_type *root_face_lucky_elem = NULL;
- struct bt_field_type *root_cats = NULL;
- struct bt_field_type *root_dream = NULL;
- struct bt_field_type *root_dream_elem = NULL;
- struct bt_field_type *root_dream_elem_elem = NULL;
- struct bt_field_type *root_dream_elem_elem_elem = NULL;
- struct bt_field_type *root_stream_id = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_face = bt_field_type_structure_create();
- BT_ASSERT(root_face);
- ret = bt_field_type_set_alignment(root_face, 8);
- BT_ASSERT(ret == 0);
- root_face_branch_elem = bt_field_type_string_create();
- BT_ASSERT(root_face_branch_elem);
- ret = bt_field_type_string_set_encoding(root_face_branch_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_face_branch = bt_field_type_sequence_create(root_face_branch_elem, "serious");
- BT_ASSERT(root_face_branch);
- ret = bt_field_type_structure_add_field(root_face, root_face_branch, "branch");
- BT_ASSERT(ret == 0);
- root_face_income_elem = bt_field_type_string_create();
- BT_ASSERT(root_face_income_elem);
- ret = bt_field_type_string_set_encoding(root_face_income_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_face_income = bt_field_type_sequence_create(root_face_income_elem, "magic");
- BT_ASSERT(root_face_income);
- ret = bt_field_type_structure_add_field(root_face, root_face_income, "income");
- BT_ASSERT(ret == 0);
- root_face_magic = bt_field_type_integer_create(23);
- BT_ASSERT(root_face_magic);
- ret = bt_field_type_integer_set_is_signed(root_face_magic, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_face_magic, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_face_magic, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_face_magic, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_face_magic, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_face, root_face_magic, "magic");
- BT_ASSERT(ret == 0);
- root_face_lucky_elem = bt_field_type_string_create();
- BT_ASSERT(root_face_lucky_elem);
- ret = bt_field_type_string_set_encoding(root_face_lucky_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_face_lucky = bt_field_type_sequence_create(root_face_lucky_elem, "magic");
- BT_ASSERT(root_face_lucky);
- ret = bt_field_type_structure_add_field(root_face, root_face_lucky, "lucky");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_face, "face");
- BT_ASSERT(ret == 0);
- root_cats = bt_field_type_integer_create(5);
- BT_ASSERT(root_cats);
- ret = bt_field_type_integer_set_is_signed(root_cats, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_cats, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_cats, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_cats, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_cats, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_cats, "cats");
- BT_ASSERT(ret == 0);
- root_dream_elem_elem_elem = bt_field_type_string_create();
- BT_ASSERT(root_dream_elem_elem_elem);
- ret = bt_field_type_string_set_encoding(root_dream_elem_elem_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_dream_elem_elem = bt_field_type_sequence_create(root_dream_elem_elem_elem, "stream.event.context.face.magic");
- BT_ASSERT(root_dream_elem_elem);
- root_dream_elem = bt_field_type_sequence_create(root_dream_elem_elem, "trace.packet.header.iron.dust");
- BT_ASSERT(root_dream_elem);
- root_dream = bt_field_type_sequence_create(root_dream_elem, "stream.packet.context.placid");
- BT_ASSERT(root_dream);
- ret = bt_field_type_structure_add_field(root, root_dream, "dream");
- BT_ASSERT(ret == 0);
- root_stream_id = bt_field_type_integer_create(9);
- BT_ASSERT(root_stream_id);
- ret = bt_field_type_integer_set_is_signed(root_stream_id, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_stream_id, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_stream_id, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_stream_id, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_stream_id, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_stream_id, "stream_id");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_face);
- BT_PUT(root_face_branch);
- BT_PUT(root_face_branch_elem);
- BT_PUT(root_face_income);
- BT_PUT(root_face_income_elem);
- BT_PUT(root_face_magic);
- BT_PUT(root_face_lucky);
- BT_PUT(root_face_lucky_elem);
- BT_PUT(root_cats);
- BT_PUT(root_dream);
- BT_PUT(root_dream_elem);
- BT_PUT(root_dream_elem_elem);
- BT_PUT(root_dream_elem_elem_elem);
- BT_PUT(root_stream_id);
-
- return root;
-}
-
-static
-struct bt_field_type *get_good_event_context_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- film:
- class: int
- size: 19
- berry:
- class: struct
- fields:
- pine:
- class: array
- length: stream_id
- element-type:
- class: string
- porter:
- class: array
- length: face.magic
- element-type:
- class: string
- mice:
- class: array
- length: action.special
- element-type:
- class: string
- third:
- class: int
- size: 18
- guard:
- class: array
- length: clover.oval
- element-type:
- class: string
- one:
- class: array
- length: iron.fire.word
- element-type:
- class: string
- cats:
- class: int
- size: 55
- loud:
- class: struct
- fields:
- toys:
- class: array
- length: trace.packet.header.iron.fire.word
- element-type:
- class: string
- spoon:
- class: array
- length: stream.packet.context.clover.oval
- element-type:
- class: string
- turkey:
- class: array
- length: stream.event.header.action.special
- element-type:
- class: string
- inform:
- class: array
- length: stream.event.context.face.magic
- element-type:
- class: string
- odd:
- class: array
- length: berry.third
- element-type:
- class: string
- amuck:
- class: array
- length: event.context.film
- element-type:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_film = NULL;
- struct bt_field_type *root_berry = NULL;
- struct bt_field_type *root_berry_pine = NULL;
- struct bt_field_type *root_berry_pine_elem = NULL;
- struct bt_field_type *root_berry_porter = NULL;
- struct bt_field_type *root_berry_porter_elem = NULL;
- struct bt_field_type *root_berry_mice = NULL;
- struct bt_field_type *root_berry_mice_elem = NULL;
- struct bt_field_type *root_berry_third = NULL;
- struct bt_field_type *root_berry_guard = NULL;
- struct bt_field_type *root_berry_guard_elem = NULL;
- struct bt_field_type *root_berry_one = NULL;
- struct bt_field_type *root_berry_one_elem = NULL;
- struct bt_field_type *root_cats = NULL;
- struct bt_field_type *root_loud = NULL;
- struct bt_field_type *root_loud_toys = NULL;
- struct bt_field_type *root_loud_toys_elem = NULL;
- struct bt_field_type *root_loud_spoon = NULL;
- struct bt_field_type *root_loud_spoon_elem = NULL;
- struct bt_field_type *root_loud_turkey = NULL;
- struct bt_field_type *root_loud_turkey_elem = NULL;
- struct bt_field_type *root_loud_inform = NULL;
- struct bt_field_type *root_loud_inform_elem = NULL;
- struct bt_field_type *root_loud_odd = NULL;
- struct bt_field_type *root_loud_odd_elem = NULL;
- struct bt_field_type *root_loud_amuck = NULL;
- struct bt_field_type *root_loud_amuck_elem = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_film = bt_field_type_integer_create(19);
- BT_ASSERT(root_film);
- ret = bt_field_type_integer_set_is_signed(root_film, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_film, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_film, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_film, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_film, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_film, "film");
- BT_ASSERT(ret == 0);
- root_berry = bt_field_type_structure_create();
- BT_ASSERT(root_berry);
- ret = bt_field_type_set_alignment(root_berry, 8);
- BT_ASSERT(ret == 0);
- root_berry_pine_elem = bt_field_type_string_create();
- BT_ASSERT(root_berry_pine_elem);
- ret = bt_field_type_string_set_encoding(root_berry_pine_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_berry_pine = bt_field_type_sequence_create(root_berry_pine_elem, "stream_id");
- BT_ASSERT(root_berry_pine);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_pine, "pine");
- BT_ASSERT(ret == 0);
- root_berry_porter_elem = bt_field_type_string_create();
- BT_ASSERT(root_berry_porter_elem);
- ret = bt_field_type_string_set_encoding(root_berry_porter_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_berry_porter = bt_field_type_sequence_create(root_berry_porter_elem, "face.magic");
- BT_ASSERT(root_berry_porter);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_porter, "porter");
- BT_ASSERT(ret == 0);
- root_berry_mice_elem = bt_field_type_string_create();
- BT_ASSERT(root_berry_mice_elem);
- ret = bt_field_type_string_set_encoding(root_berry_mice_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_berry_mice = bt_field_type_sequence_create(root_berry_mice_elem, "action.special");
- BT_ASSERT(root_berry_mice);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_mice, "mice");
- BT_ASSERT(ret == 0);
- root_berry_third = bt_field_type_integer_create(18);
- BT_ASSERT(root_berry_third);
- ret = bt_field_type_integer_set_is_signed(root_berry_third, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_berry_third, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_berry_third, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_berry_third, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_berry_third, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_third, "third");
- BT_ASSERT(ret == 0);
- root_berry_guard_elem = bt_field_type_string_create();
- BT_ASSERT(root_berry_guard_elem);
- ret = bt_field_type_string_set_encoding(root_berry_guard_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_berry_guard = bt_field_type_sequence_create(root_berry_guard_elem, "clover.oval");
- BT_ASSERT(root_berry_guard);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_guard, "guard");
- BT_ASSERT(ret == 0);
- root_berry_one_elem = bt_field_type_string_create();
- BT_ASSERT(root_berry_one_elem);
- ret = bt_field_type_string_set_encoding(root_berry_one_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_berry_one = bt_field_type_sequence_create(root_berry_one_elem, "iron.fire.word");
- BT_ASSERT(root_berry_one);
- ret = bt_field_type_structure_add_field(root_berry, root_berry_one, "one");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_berry, "berry");
- BT_ASSERT(ret == 0);
- root_cats = bt_field_type_integer_create(55);
- BT_ASSERT(root_cats);
- ret = bt_field_type_integer_set_is_signed(root_cats, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_cats, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_cats, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_cats, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_cats, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_cats, "cats");
- BT_ASSERT(ret == 0);
- root_loud = bt_field_type_structure_create();
- BT_ASSERT(root_loud);
- ret = bt_field_type_set_alignment(root_loud, 8);
- BT_ASSERT(ret == 0);
- root_loud_toys_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_toys_elem);
- ret = bt_field_type_string_set_encoding(root_loud_toys_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_toys = bt_field_type_sequence_create(root_loud_toys_elem, "trace.packet.header.iron.fire.word");
- BT_ASSERT(root_loud_toys);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_toys, "toys");
- BT_ASSERT(ret == 0);
- root_loud_spoon_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_spoon_elem);
- ret = bt_field_type_string_set_encoding(root_loud_spoon_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_spoon = bt_field_type_sequence_create(root_loud_spoon_elem, "stream.packet.context.clover.oval");
- BT_ASSERT(root_loud_spoon);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_spoon, "spoon");
- BT_ASSERT(ret == 0);
- root_loud_turkey_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_turkey_elem);
- ret = bt_field_type_string_set_encoding(root_loud_turkey_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_turkey = bt_field_type_sequence_create(root_loud_turkey_elem, "stream.event.header.action.special");
- BT_ASSERT(root_loud_turkey);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_turkey, "turkey");
- BT_ASSERT(ret == 0);
- root_loud_inform_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_inform_elem);
- ret = bt_field_type_string_set_encoding(root_loud_inform_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_inform = bt_field_type_sequence_create(root_loud_inform_elem, "stream.event.context.face.magic");
- BT_ASSERT(root_loud_inform);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_inform, "inform");
- BT_ASSERT(ret == 0);
- root_loud_odd_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_odd_elem);
- ret = bt_field_type_string_set_encoding(root_loud_odd_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_odd = bt_field_type_sequence_create(root_loud_odd_elem, "berry.third");
- BT_ASSERT(root_loud_odd);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_odd, "odd");
- BT_ASSERT(ret == 0);
- root_loud_amuck_elem = bt_field_type_string_create();
- BT_ASSERT(root_loud_amuck_elem);
- ret = bt_field_type_string_set_encoding(root_loud_amuck_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_loud_amuck = bt_field_type_sequence_create(root_loud_amuck_elem, "event.context.film");
- BT_ASSERT(root_loud_amuck);
- ret = bt_field_type_structure_add_field(root_loud, root_loud_amuck, "amuck");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_loud, "loud");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_film);
- BT_PUT(root_berry);
- BT_PUT(root_berry_pine);
- BT_PUT(root_berry_pine_elem);
- BT_PUT(root_berry_porter);
- BT_PUT(root_berry_porter_elem);
- BT_PUT(root_berry_mice);
- BT_PUT(root_berry_mice_elem);
- BT_PUT(root_berry_third);
- BT_PUT(root_berry_guard);
- BT_PUT(root_berry_guard_elem);
- BT_PUT(root_berry_one);
- BT_PUT(root_berry_one_elem);
- BT_PUT(root_cats);
- BT_PUT(root_loud);
- BT_PUT(root_loud_toys);
- BT_PUT(root_loud_toys_elem);
- BT_PUT(root_loud_spoon);
- BT_PUT(root_loud_spoon_elem);
- BT_PUT(root_loud_turkey);
- BT_PUT(root_loud_turkey_elem);
- BT_PUT(root_loud_inform);
- BT_PUT(root_loud_inform_elem);
- BT_PUT(root_loud_odd);
- BT_PUT(root_loud_odd_elem);
- BT_PUT(root_loud_amuck);
- BT_PUT(root_loud_amuck_elem);
-
- return root;
-}
-
-static
-struct bt_field_type *get_good_event_payload_field_type(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- splendid:
- class: int
- size: 12
- relative:
- class: struct
- fields:
- equal:
- class: array
- length: splendid
- element-type:
- class: string
- amuck:
- class: array
- length: cats
- element-type:
- class: string
- push:
- class: array
- length: berry.third
- element-type:
- class: string
- brick:
- class: array
- length: face.magic
- element-type:
- class: string
- amuck:
- class: array
- length: id
- element-type:
- class: string
- crush:
- class: array
- length: serious
- element-type:
- class: string
- canvas:
- class: array
- length: iron.dust
- element-type:
- class: string
- absolute:
- class: struct
- fields:
- equal:
- class: array
- length: event.fields.splendid
- element-type:
- class: string
- amuck:
- class: array
- length: event.context.cats
- element-type:
- class: string
- push:
- class: array
- length: event.context.berry.third
- element-type:
- class: string
- brick:
- class: array
- length: stream.event.context.face.magic
- element-type:
- class: string
- amuck:
- class: array
- length: stream.event.header.id
- element-type:
- class: string
- crush:
- class: array
- length: stream.packet.context.serious
- element-type:
- class: string
- canvas:
- class: array
- length: trace.packet.header.iron.dust
- element-type:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_splendid = NULL;
- struct bt_field_type *root_relative = NULL;
- struct bt_field_type *root_relative_equal = NULL;
- struct bt_field_type *root_relative_equal_elem = NULL;
- struct bt_field_type *root_relative_amuck = NULL;
- struct bt_field_type *root_relative_amuck_elem = NULL;
- struct bt_field_type *root_relative_push = NULL;
- struct bt_field_type *root_relative_push_elem = NULL;
- struct bt_field_type *root_relative_brick = NULL;
- struct bt_field_type *root_relative_brick_elem = NULL;
- struct bt_field_type *root_relative_crush = NULL;
- struct bt_field_type *root_relative_crush_elem = NULL;
- struct bt_field_type *root_relative_canvas = NULL;
- struct bt_field_type *root_relative_canvas_elem = NULL;
- struct bt_field_type *root_absolute = NULL;
- struct bt_field_type *root_absolute_equal = NULL;
- struct bt_field_type *root_absolute_equal_elem = NULL;
- struct bt_field_type *root_absolute_amuck = NULL;
- struct bt_field_type *root_absolute_amuck_elem = NULL;
- struct bt_field_type *root_absolute_push = NULL;
- struct bt_field_type *root_absolute_push_elem = NULL;
- struct bt_field_type *root_absolute_brick = NULL;
- struct bt_field_type *root_absolute_brick_elem = NULL;
- struct bt_field_type *root_absolute_crush = NULL;
- struct bt_field_type *root_absolute_crush_elem = NULL;
- struct bt_field_type *root_absolute_canvas = NULL;
- struct bt_field_type *root_absolute_canvas_elem = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_splendid = bt_field_type_integer_create(12);
- BT_ASSERT(root_splendid);
- ret = bt_field_type_integer_set_is_signed(root_splendid, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_splendid, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_splendid, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_splendid, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_splendid, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_splendid, "splendid");
- BT_ASSERT(ret == 0);
- root_relative = bt_field_type_structure_create();
- BT_ASSERT(root_relative);
- ret = bt_field_type_set_alignment(root_relative, 8);
- BT_ASSERT(ret == 0);
- root_relative_equal_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_equal_elem);
- ret = bt_field_type_string_set_encoding(root_relative_equal_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_equal = bt_field_type_sequence_create(root_relative_equal_elem, "splendid");
- BT_ASSERT(root_relative_equal);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_equal, "equal");
- BT_ASSERT(ret == 0);
- root_relative_amuck_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_amuck_elem);
- ret = bt_field_type_string_set_encoding(root_relative_amuck_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_amuck = bt_field_type_sequence_create(root_relative_amuck_elem, "id");
- BT_ASSERT(root_relative_amuck);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_amuck, "amuck");
- BT_ASSERT(ret == 0);
- root_relative_push_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_push_elem);
- ret = bt_field_type_string_set_encoding(root_relative_push_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_push = bt_field_type_sequence_create(root_relative_push_elem, "berry.third");
- BT_ASSERT(root_relative_push);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_push, "push");
- BT_ASSERT(ret == 0);
- root_relative_brick_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_brick_elem);
- ret = bt_field_type_string_set_encoding(root_relative_brick_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_brick = bt_field_type_sequence_create(root_relative_brick_elem, "face.magic");
- BT_ASSERT(root_relative_brick);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_brick, "brick");
- BT_ASSERT(ret == 0);
- root_relative_crush_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_crush_elem);
- ret = bt_field_type_string_set_encoding(root_relative_crush_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_crush = bt_field_type_sequence_create(root_relative_crush_elem, "serious");
- BT_ASSERT(root_relative_crush);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_crush, "crush");
- BT_ASSERT(ret == 0);
- root_relative_canvas_elem = bt_field_type_string_create();
- BT_ASSERT(root_relative_canvas_elem);
- ret = bt_field_type_string_set_encoding(root_relative_canvas_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_relative_canvas = bt_field_type_sequence_create(root_relative_canvas_elem, "iron.dust");
- BT_ASSERT(root_relative_canvas);
- ret = bt_field_type_structure_add_field(root_relative, root_relative_canvas, "canvas");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_relative, "relative");
- BT_ASSERT(ret == 0);
- root_absolute = bt_field_type_structure_create();
- BT_ASSERT(root_absolute);
- ret = bt_field_type_set_alignment(root_absolute, 8);
- BT_ASSERT(ret == 0);
- root_absolute_equal_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_equal_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_equal_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_equal = bt_field_type_sequence_create(root_absolute_equal_elem, "event.fields.splendid");
- BT_ASSERT(root_absolute_equal);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_equal, "equal");
- BT_ASSERT(ret == 0);
- root_absolute_amuck_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_amuck_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_amuck_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_amuck = bt_field_type_sequence_create(root_absolute_amuck_elem, "stream.event.header.id");
- BT_ASSERT(root_absolute_amuck);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_amuck, "amuck");
- BT_ASSERT(ret == 0);
- root_absolute_push_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_push_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_push_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_push = bt_field_type_sequence_create(root_absolute_push_elem, "event.context.berry.third");
- BT_ASSERT(root_absolute_push);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_push, "push");
- BT_ASSERT(ret == 0);
- root_absolute_brick_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_brick_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_brick_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_brick = bt_field_type_sequence_create(root_absolute_brick_elem, "stream.event.context.face.magic");
- BT_ASSERT(root_absolute_brick);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_brick, "brick");
- BT_ASSERT(ret == 0);
- root_absolute_crush_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_crush_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_crush_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_crush = bt_field_type_sequence_create(root_absolute_crush_elem, "stream.packet.context.serious");
- BT_ASSERT(root_absolute_crush);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_crush, "crush");
- BT_ASSERT(ret == 0);
- root_absolute_canvas_elem = bt_field_type_string_create();
- BT_ASSERT(root_absolute_canvas_elem);
- ret = bt_field_type_string_set_encoding(root_absolute_canvas_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_absolute_canvas = bt_field_type_sequence_create(root_absolute_canvas_elem, "trace.packet.header.iron.dust");
- BT_ASSERT(root_absolute_canvas);
- ret = bt_field_type_structure_add_field(root_absolute, root_absolute_canvas, "canvas");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_absolute, "absolute");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_splendid);
- BT_PUT(root_relative);
- BT_PUT(root_relative_equal);
- BT_PUT(root_relative_equal_elem);
- BT_PUT(root_relative_amuck);
- BT_PUT(root_relative_amuck_elem);
- BT_PUT(root_relative_push);
- BT_PUT(root_relative_push_elem);
- BT_PUT(root_relative_brick);
- BT_PUT(root_relative_brick_elem);
- BT_PUT(root_relative_crush);
- BT_PUT(root_relative_crush_elem);
- BT_PUT(root_relative_canvas);
- BT_PUT(root_relative_canvas_elem);
- BT_PUT(root_absolute);
- BT_PUT(root_absolute_equal);
- BT_PUT(root_absolute_equal_elem);
- BT_PUT(root_absolute_amuck);
- BT_PUT(root_absolute_amuck_elem);
- BT_PUT(root_absolute_push);
- BT_PUT(root_absolute_push_elem);
- BT_PUT(root_absolute_brick);
- BT_PUT(root_absolute_brick_elem);
- BT_PUT(root_absolute_crush);
- BT_PUT(root_absolute_crush_elem);
- BT_PUT(root_absolute_canvas);
- BT_PUT(root_absolute_canvas_elem);
-
- return root;
-}
-
-static
-struct bt_field_type *get_child_ft(struct bt_field_type *parent_ft,
- const char *name)
-{
- struct bt_field_type *ft = NULL;
-
- switch (bt_field_type_get_type_id(parent_ft)) {
- case BT_FIELD_TYPE_ID_STRUCT:
- ft = bt_field_type_structure_get_field_type_by_name(
- parent_ft, name);
- break;
-
- case BT_FIELD_TYPE_ID_VARIANT:
- ft = bt_field_type_variant_get_field_type_by_name(
- parent_ft, name);
- break;
-
- case BT_FIELD_TYPE_ID_ARRAY:
- ft = bt_field_type_array_get_element_field_type(parent_ft);
- break;
-
- case BT_FIELD_TYPE_ID_SEQUENCE:
- ft = bt_field_type_sequence_get_element_field_type(parent_ft);
- break;
-
- case BT_FIELD_TYPE_ID_ENUM:
- ft = bt_field_type_enumeration_get_container_field_type(
- parent_ft);
- break;
-
- default:
- break;
- }
-
- BT_ASSERT(ft);
-
- return ft;
-}
-
-static
-struct bt_field_type *get_ft(struct bt_field_type *root_ft, ...)
-{
- struct bt_field_type *child_ft = NULL;
- struct bt_field_type *ft = root_ft;
- va_list ap;
-
- va_start(ap, root_ft);
- bt_get(ft);
-
- while (true) {
- const char *field_name = va_arg(ap, const char *);
-
- if (field_name == NULL) {
- break;
- }
-
- child_ft = get_child_ft(ft, field_name);
-
- if (!child_ft) {
- BT_PUT(ft);
- goto end;
- }
-
- BT_MOVE(ft, child_ft);
- }
-
-end:
- va_end(ap);
-
- return ft;
-}
-
-#define FIELD_PATH_END -2
-
-static
-int validate_field_path(struct bt_field_type *field_type, int int_root, ...)
-{
- enum bt_scope root = int_root;
- int ret = 0;
- int len;
- int expected_index;
- int actual_index;
- int i = 0;
- struct bt_field_path *field_path = NULL;
- va_list ap;
-
- va_start(ap, int_root);
- if (bt_field_type_is_sequence(field_type)) {
- field_path = bt_field_type_sequence_get_length_field_path(
- field_type);
- } else if (bt_field_type_is_variant(field_type)) {
- field_path = bt_field_type_variant_get_tag_field_path(
- field_type);
- }
-
- if (!field_path) {
- ret = -1;
- goto end;
- }
-
- if (bt_field_path_get_root_scope(field_path) != root) {
- ret = -1;
- goto end;
- }
-
- len = bt_field_path_get_index_count(field_path);
-
- while (true) {
- expected_index = va_arg(ap, int);
-
- if (expected_index == FIELD_PATH_END) {
- break;
- }
-
- if (i == len) {
- break;
- }
-
- actual_index = bt_field_path_get_index(field_path, i);
-
- if (actual_index == INT_MIN) {
- ret = -1;
- goto end;
- }
-
- i++;
- }
-
- if (i != len || expected_index != FIELD_PATH_END) {
- ret = -1;
- }
-
-end:
- BT_PUT(field_path);
- va_end(ap);
-
- return ret;
-}
-
-static
-void validate_test_pass(struct bt_trace *trace)
-{
- struct bt_stream_class *sc;
- struct bt_event_class *ec;
- struct bt_field_type *ph;
- struct bt_field_type *pc;
- struct bt_field_type *eh;
- struct bt_field_type *sec;
- struct bt_field_type *ectx;
- struct bt_field_type *ep;
- struct bt_field_type *ft_src = NULL;
- struct bt_field_type *ft_target = NULL;
- struct bt_field_type *ft_tag = NULL;
-
- sc = bt_trace_get_stream_class_by_index(trace, 0);
- BT_ASSERT(sc);
- ec = bt_stream_class_get_event_class_by_index(sc, 0);
- BT_ASSERT(ec);
-
- ph = bt_trace_get_packet_header_field_type(trace);
- ok(ph, "Trace packet header still exists after successful validation");
- pc = bt_stream_class_get_packet_context_field_type(sc);
- ok(pc, "Stream packet context still exists after successful validation");
- eh = bt_stream_class_get_event_header_field_type(sc);
- ok(eh, "Stream event header still exists after successful validation");
- sec = bt_stream_class_get_event_context_field_type(sc);
- ok(sec, "Stream event context still exists after successful validation");
- ectx = bt_event_class_get_context_field_type(ec);
- ok(ectx, "Event context still exists after successful validation");
- ep = bt_event_class_get_payload_field_type(ec);
- ok(ep, "Event payload still exists after successful validation");
-
- /* trace.packet.header.iron.fire.keen */
- ft_src = get_ft(ph, "iron", "fire", "keen", NULL);
- ok(!validate_field_path(ft_src, BT_SCOPE_TRACE_PACKET_HEADER,
- 3, 3, 0, FIELD_PATH_END),
- "trace.packet.header.iron.fire.keen has the correct field path");
- BT_PUT(ft_src);
-
- /* trace.packet.header.iron.fire.keen.[element] */
- ft_src = get_ft(ph, "iron", "fire", "keen", "", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 2, FIELD_PATH_END),
- "trace.packet.header.iron.fire.keen.[element] has the correct field path");
- ft_target = get_ft(ph, "iron", "parallel", NULL);
- ft_tag = bt_field_type_variant_get_tag_field_type(ft_src);
- ok(ft_tag == ft_target,
- "trace.packet.header.iron.fire.keen.[element] has the correct tag type");
- BT_PUT(ft_src);
- BT_PUT(ft_target);
- BT_PUT(ft_tag);
-
- /* trace.packet.header.iron.fire.keen.[element].BLUE */
- ft_src = get_ft(ph, "iron", "fire", "keen", "", "BLUE", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 0, FIELD_PATH_END),
- "trace.packet.header.iron.fire.keen.[element].BLUE has the correct field path");
- BT_PUT(ft_src);
-
- /* trace.packet.header.iron.report */
- ft_src = get_ft(ph, "iron", "report", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 1, FIELD_PATH_END),
- "trace.packet.header.iron.report has the correct field path");
- BT_PUT(ft_src);
-
- /* trace.packet.header.iron.group */
- ft_src = get_ft(ph, "iron", "group", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 2, FIELD_PATH_END),
- "trace.packet.header.iron.group has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.packet.context.naive.[element] */
- ft_src = get_ft(pc, "naive", "", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 0, FIELD_PATH_END),
- "stream.packet.context.naive.[element] has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.packet.context.clover.whole */
- ft_src = get_ft(pc, "clover", "whole", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 2, FIELD_PATH_END),
- "stream.packet.context.clover.whole has the correct field path");
- ft_target = get_ft(ph, "iron", "parallel", NULL);
- ft_tag = bt_field_type_variant_get_tag_field_type(ft_src);
- ok(ft_tag == ft_target,
- "stream.packet.context.clover.whole has the correct tag type");
- BT_PUT(ft_src);
- BT_PUT(ft_target);
- BT_PUT(ft_tag);
-
- /* stream.packet.context.clover.whole.BLUE */
- ft_src = get_ft(pc, "clover", "whole", "BLUE", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 3, 0, FIELD_PATH_END),
- "stream.packet.context.clover.whole.BLUE has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.packet.context.clover.egg */
- ft_src = get_ft(pc, "clover", "egg", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 4, 0, FIELD_PATH_END),
- "stream.packet.context.clover.egg has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.packet.context.clover.useful */
- ft_src = get_ft(pc, "clover", "useful", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 2, FIELD_PATH_END),
- "stream.packet.context.clover.useful has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.header.action.lucky */
- ft_src = get_ft(eh, "action", "lucky", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 0, FIELD_PATH_END),
- "stream.event.header.action.lucky has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.header.stiff */
- ft_src = get_ft(eh, "stiff", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 4, 1, 1, FIELD_PATH_END),
- "stream.event.header.stiff has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.header.fruit.apple */
- ft_src = get_ft(eh, "fruit", "apple", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_HEADER, 2, 0, FIELD_PATH_END),
- "stream.event.header.fruit.apple has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.face.branch */
- ft_src = get_ft(sec, "face", "branch", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 2, FIELD_PATH_END),
- "stream.event.context.face.branch has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.face.income */
- ft_src = get_ft(sec, "face", "income", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 0, FIELD_PATH_END),
- "stream.event.context.face.income has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.face.lucky */
- ft_src = get_ft(sec, "face", "lucky", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "stream.event.context.face.lucky has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.dream */
- ft_src = get_ft(sec, "dream", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 0, FIELD_PATH_END),
- "stream.event.context.dream has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.dream.[element] */
- ft_src = get_ft(sec, "dream", "", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 1, FIELD_PATH_END),
- "stream.event.context.dream.[element] has the correct field path");
- BT_PUT(ft_src);
-
- /* stream.event.context.dream.[element].[element] */
- ft_src = get_ft(sec, "dream", "", "", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "stream.event.context.dream.[element].[element] has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.berry.porter */
- ft_src = get_ft(ectx, "berry", "porter", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "event.context.berry.porter has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.berry.porter */
- ft_src = get_ft(ectx, "berry", "porter", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "event.context.berry.porter has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.berry.mice */
- ft_src = get_ft(ectx, "berry", "mice", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_HEADER, 2, 0, FIELD_PATH_END),
- "event.context.berry.mice has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.berry.guard */
- ft_src = get_ft(ectx, "berry", "guard", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 4, 0, FIELD_PATH_END),
- "event.context.berry.guard has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.berry.one */
- ft_src = get_ft(ectx, "berry", "one", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 3, 0, FIELD_PATH_END),
- "event.context.berry.one has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.toys */
- ft_src = get_ft(ectx, "loud", "toys", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 3, 0, FIELD_PATH_END),
- "event.context.loud.toys has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.spoon */
- ft_src = get_ft(ectx, "loud", "spoon", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 4, 0, FIELD_PATH_END),
- "event.context.loud.spoon has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.turkey */
- ft_src = get_ft(ectx, "loud", "turkey", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_HEADER, 2, 0, FIELD_PATH_END),
- "event.context.loud.turkey has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.inform */
- ft_src = get_ft(ectx, "loud", "inform", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "event.context.loud.inform has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.odd */
- ft_src = get_ft(ectx, "loud", "odd", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_CONTEXT, 1, 3, FIELD_PATH_END),
- "event.context.loud.odd has the correct field path");
- BT_PUT(ft_src);
-
- /* event.context.loud.amuck */
- ft_src = get_ft(ectx, "loud", "amuck", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_CONTEXT, 0, FIELD_PATH_END),
- "event.context.loud.amuck has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.equal */
- ft_src = get_ft(ep, "relative", "equal", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_FIELDS, 0, FIELD_PATH_END),
- "event.fields.relative.equal has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.amuck */
- ft_src = get_ft(ep, "relative", "amuck", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_HEADER, 0, FIELD_PATH_END),
- "event.fields.relative.amuck has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.push */
- ft_src = get_ft(ep, "relative", "push", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_CONTEXT, 1, 3, FIELD_PATH_END),
- "event.fields.relative.push has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.brick */
- ft_src = get_ft(ep, "relative", "brick", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "event.fields.relative.brick has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.crush */
- ft_src = get_ft(ep, "relative", "crush", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 2, FIELD_PATH_END),
- "event.fields.relative.crush has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.relative.canvas */
- ft_src = get_ft(ep, "relative", "canvas", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 1, FIELD_PATH_END),
- "event.fields.relative.canvas has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.equal */
- ft_src = get_ft(ep, "absolute", "equal", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_FIELDS, 0, FIELD_PATH_END),
- "event.fields.absolute.equal has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.amuck */
- ft_src = get_ft(ep, "absolute", "amuck", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_HEADER, 0, FIELD_PATH_END),
- "event.fields.absolute.amuck has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.push */
- ft_src = get_ft(ep, "absolute", "push", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_EVENT_CONTEXT, 1, 3, FIELD_PATH_END),
- "event.fields.absolute.push has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.brick */
- ft_src = get_ft(ep, "absolute", "brick", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_EVENT_CONTEXT, 0, 2, FIELD_PATH_END),
- "event.fields.absolute.brick has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.crush */
- ft_src = get_ft(ep, "absolute", "crush", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_STREAM_PACKET_CONTEXT, 2, FIELD_PATH_END),
- "event.fields.absolute.crush has the correct field path");
- BT_PUT(ft_src);
-
- /* event.fields.absolute.canvas */
- ft_src = get_ft(ep, "absolute", "canvas", NULL);
- ok(!validate_field_path(ft_src,
- BT_SCOPE_TRACE_PACKET_HEADER, 3, 1, FIELD_PATH_END),
- "event.fields.absolute.canvas has the correct field path");
- BT_PUT(ft_src);
-
- BT_PUT(ft_src);
- BT_PUT(ft_target);
- BT_PUT(ph);
- BT_PUT(pc);
- BT_PUT(eh);
- BT_PUT(sec);
- BT_PUT(ectx);
- BT_PUT(ep);
- BT_PUT(sc);
- BT_PUT(ec);
-}
-
-static
-void test_pass(void)
-{
- int ret;
- struct bt_trace *trace;
- struct bt_stream_class *sc;
- struct bt_event_class *ec;
- struct bt_field_type *ph;
- struct bt_field_type *pc;
- struct bt_field_type *eh;
- struct bt_field_type *sec;
- struct bt_field_type *ectx;
- struct bt_field_type *ep;
-
- trace = bt_trace_create();
- BT_ASSERT(trace);
- sc = bt_stream_class_create("nice_piece_of_stream_class");
- BT_ASSERT(sc);
- ec = bt_event_class_create("oh_what_an_event_class");
- BT_ASSERT(ec);
-
- ph = get_good_packet_header_field_type();
- BT_ASSERT(ph);
- pc = get_good_packet_context_field_type();
- BT_ASSERT(pc);
- eh = get_good_event_header_field_type();
- BT_ASSERT(eh);
- sec = get_good_stream_event_context_field_type();
- BT_ASSERT(sec);
- ectx = get_good_event_context_field_type();
- BT_ASSERT(ec);
- ep = get_good_event_payload_field_type();
- BT_ASSERT(ep);
-
- ret = bt_trace_set_packet_header_field_type(trace, ph);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_packet_context_field_type(sc, pc);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_header_field_type(sc, eh);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_context_field_type(sc, sec);
- BT_ASSERT(ret == 0);
- ret = bt_event_class_set_context_field_type(ec, ectx);
- BT_ASSERT(ret == 0);
- ret = bt_event_class_set_payload_field_type(ec, ep);
- BT_ASSERT(ret == 0);
-
- ret = bt_stream_class_add_event_class(sc, ec);
- BT_ASSERT(ret == 0);
-
- /* Validation happens here */
- ret = bt_trace_add_stream_class(trace, sc);
- ok(ret == 0, "Valid type system is considered valid");
-
- validate_test_pass(trace);
-
- BT_PUT(ph);
- BT_PUT(pc);
- BT_PUT(eh);
- BT_PUT(sec);
- BT_PUT(ectx);
- BT_PUT(ep);
- BT_PUT(trace);
- BT_PUT(sc);
- BT_PUT(ec);
-}
-
-static
-int try_add_event_class_to_trace(struct bt_field_type *ectx,
- struct bt_field_type *ep)
-{
- int ret;
- struct bt_trace *trace;
- struct bt_stream_class *sc;
- struct bt_event_class *ec;
-
- trace = bt_trace_create();
- BT_ASSERT(trace);
- sc = bt_stream_class_create("sc");
- BT_ASSERT(sc);
- ec = bt_event_class_create("ec");
- BT_ASSERT(ec);
-
- if (ectx) {
- ret = bt_event_class_set_context_field_type(ec, ectx);
- BT_ASSERT(ret == 0);
- }
-
- if (ep) {
- ret = bt_event_class_set_payload_field_type(ec, ep);
- BT_ASSERT(ret == 0);
- }
-
- ret = bt_stream_class_add_event_class(sc, ec);
- BT_ASSERT(ret == 0);
- ret = bt_trace_add_stream_class(trace, sc);
- BT_PUT(ec);
- BT_PUT(sc);
- BT_PUT(trace);
- return ret;
-}
-
-static
-struct bt_field_type *test_fail_unavailable_root_get_event_payload(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- b:
- class: array
- length: stream.event.context.lol
- element-type:
- class: string
- c:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_b_elem);
- ret = bt_field_type_string_set_encoding(root_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_sequence_create(root_b_elem, "stream.event.context.lol");
- BT_ASSERT(root_b);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_elem);
- BT_PUT(root_c);
-
- return root;
-}
-
-static
-void test_fail_unavailable_root(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_unavailable_root_get_event_payload();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with length in unavailable root is invalid");
-
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_target_is_root_get_event_payload(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- b:
- class: array
- length: event.fields
- element-type:
- class: string
- c:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_b_elem);
- ret = bt_field_type_string_set_encoding(root_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_sequence_create(root_b_elem, "event.fields");
- BT_ASSERT(root_b);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_elem);
- BT_PUT(root_c);
-
- return root;
-}
-
-static
-void test_fail_target_is_root(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_target_is_root_get_event_payload();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with root as its length is invalid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_target_is_after_source_get_ep(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- b:
- class: array
- length: d
- element-type:
- class: string
- c:
- class: string
- d:
- class: int
- size: 17
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
- struct bt_field_type *root_d = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_b_elem);
- ret = bt_field_type_string_set_encoding(root_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_sequence_create(root_b_elem, "d");
- BT_ASSERT(root_b);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
- root_d = bt_field_type_integer_create(17);
- BT_ASSERT(root_d);
- ret = bt_field_type_integer_set_is_signed(root_d, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_d, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_d, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_d, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_d, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_d, "d");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_elem);
- BT_PUT(root_c);
- BT_PUT(root_d);
-
- return root;
-}
-
-static
-void test_fail_target_is_after_source(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_target_is_after_source_get_ep();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with length after it is invalid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_target_is_ancestor_of_source_get_ep(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- z:
- class: struct
- fields:
- b:
- class: array
- length: z
- element-type:
- class: string
- c:
- class: string
- d:
- class: int
- size: 17
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_z = NULL;
- struct bt_field_type *root_z_b = NULL;
- struct bt_field_type *root_z_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
- struct bt_field_type *root_d = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_z = bt_field_type_structure_create();
- BT_ASSERT(root_z);
- ret = bt_field_type_set_alignment(root_z, 8);
- BT_ASSERT(ret == 0);
- root_z_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_z_b_elem);
- ret = bt_field_type_string_set_encoding(root_z_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_z_b = bt_field_type_sequence_create(root_z_b_elem, "z");
- BT_ASSERT(root_z_b);
- ret = bt_field_type_structure_add_field(root_z, root_z_b, "b");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_z, "z");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
- root_d = bt_field_type_integer_create(17);
- BT_ASSERT(root_d);
- ret = bt_field_type_integer_set_is_signed(root_d, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_d, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_d, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_d, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_d, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_d, "d");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_z);
- BT_PUT(root_z_b);
- BT_PUT(root_z_b_elem);
- BT_PUT(root_c);
- BT_PUT(root_d);
-
- return root;
-}
-
-static
-void test_fail_target_is_ancestor_of_source(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_target_is_ancestor_of_source_get_ep();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with ancestor as its length is invalid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_target_is_source_get_event_payload(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- b:
- class: array
- length: event.fields.b
- element-type:
- class: string
- c:
- class: string
- d:
- class: int
- size: 17
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
- struct bt_field_type *root_d = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_b_elem);
- ret = bt_field_type_string_set_encoding(root_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_sequence_create(root_b_elem, "event.fields.b");
- BT_ASSERT(root_b);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
- root_d = bt_field_type_integer_create(17);
- BT_ASSERT(root_d);
- ret = bt_field_type_integer_set_is_signed(root_d, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_d, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_d, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_d, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_d, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_d, "d");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_elem);
- BT_PUT(root_c);
- BT_PUT(root_d);
-
- return root;
-}
-
-static
-void test_fail_target_is_source(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_target_is_source_get_event_payload();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with itself as its length is invalid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_variant_tag_is_not_enum_get_ep(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: int
- size: 32
- b:
- class: variant
- tag: a
- types:
- HELLO:
- class: string
- c:
- class: string
- d:
- class: int
- size: 17
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_HELLO = NULL;
- struct bt_field_type *root_c = NULL;
- struct bt_field_type *root_d = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_integer_create(32);
- BT_ASSERT(root_a);
- ret = bt_field_type_integer_set_is_signed(root_a, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a, 8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_variant_create(NULL, "a");
- BT_ASSERT(root_b);
- root_b_HELLO = bt_field_type_string_create();
- BT_ASSERT(root_b_HELLO);
- ret = bt_field_type_string_set_encoding(root_b_HELLO, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_b, root_b_HELLO, "HELLO");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
- root_d = bt_field_type_integer_create(17);
- BT_ASSERT(root_d);
- ret = bt_field_type_integer_set_is_signed(root_d, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_d, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_d, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_d, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_d, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_d, "d");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_HELLO);
- BT_PUT(root_c);
- BT_PUT(root_d);
-
- return root;
-}
-
-static
-void test_fail_variant_tag_is_not_enum(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_variant_tag_is_not_enum_get_ep();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Variant FT with non-enum FT as its tag FT is invalid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_variant_tag_mismatch_mappings_get_ep(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: enum
- value-type:
- class: int
- size: 16
- members:
- - GLASS
- - OF
- - WATER
- b:
- class: variant
- tag: a
- types:
- GLASS:
- class: string
- OF:
- class: int
- size: 2
- c:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_a_int = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_GLASS = NULL;
- struct bt_field_type *root_b_OF = NULL;
- struct bt_field_type *root_c = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a_int = bt_field_type_integer_create(16);
- BT_ASSERT(root_a_int);
- ret = bt_field_type_integer_set_is_signed(root_a_int, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_a_int, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_a_int, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_a_int, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_a_int, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_enumeration_create(root_a_int);
- BT_ASSERT(root_a);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "GLASS", 0, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "OF", 1, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "WATER", 2, 2);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_variant_create(NULL, "a");
- BT_ASSERT(root_b);
- root_b_GLASS = bt_field_type_string_create();
- BT_ASSERT(root_b_GLASS);
- ret = bt_field_type_string_set_encoding(root_b_GLASS, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_b, root_b_GLASS, "GLASS");
- BT_ASSERT(ret == 0);
- root_b_OF = bt_field_type_integer_create(2);
- BT_ASSERT(root_b_OF);
- ret = bt_field_type_integer_set_is_signed(root_b_OF, 0);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_base(root_b_OF, 10);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_encoding(root_b_OF, BT_STRING_ENCODING_NONE);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_byte_order(root_b_OF, BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_set_alignment(root_b_OF, 1);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_variant_add_field(root_b, root_b_OF, "OF");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_a_int);
- BT_PUT(root_b);
- BT_PUT(root_b_GLASS);
- BT_PUT(root_b_OF);
- BT_PUT(root_c);
-
- return root;
-}
-
-static
-void test_fail_variant_tag_mismatch_mappings(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_variant_tag_mismatch_mappings_get_ep();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep) == 0,
- "Variant FT with mismatching tag FT is valid");
- BT_PUT(ep);
-}
-
-static
-struct bt_field_type *test_fail_sequence_tag_is_not_int_get_ep(void)
-{
- /*
- Generated by bt-ctfirtg using the following input:
-
- class: struct
- fields:
- a:
- class: string
- b:
- class: array
- length: a
- element-type:
- class: string
- c:
- class: string
-
- */
-
- struct bt_field_type *root = NULL;
- struct bt_field_type *root_a = NULL;
- struct bt_field_type *root_b = NULL;
- struct bt_field_type *root_b_elem = NULL;
- struct bt_field_type *root_c = NULL;
-
- int ret;
- root = bt_field_type_structure_create();
- BT_ASSERT(root);
- ret = bt_field_type_set_alignment(root, 8);
- BT_ASSERT(ret == 0);
- root_a = bt_field_type_string_create();
- BT_ASSERT(root_a);
- ret = bt_field_type_string_set_encoding(root_a, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_a, "a");
- BT_ASSERT(ret == 0);
- root_b_elem = bt_field_type_string_create();
- BT_ASSERT(root_b_elem);
- ret = bt_field_type_string_set_encoding(root_b_elem, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- root_b = bt_field_type_sequence_create(root_b_elem, "a");
- BT_ASSERT(root_b);
- ret = bt_field_type_structure_add_field(root, root_b, "b");
- BT_ASSERT(ret == 0);
- root_c = bt_field_type_string_create();
- BT_ASSERT(root_c);
- ret = bt_field_type_string_set_encoding(root_c, BT_STRING_ENCODING_UTF8);
- BT_ASSERT(ret == 0);
- ret = bt_field_type_structure_add_field(root, root_c, "c");
- BT_ASSERT(ret == 0);
-
- BT_PUT(root_a);
- BT_PUT(root_b);
- BT_PUT(root_b_elem);
- BT_PUT(root_c);
-
- return root;
-}
-
-static
-void test_fail_sequence_tag_is_not_int(void)
-{
- struct bt_field_type *ep;
-
- ep = test_fail_sequence_tag_is_not_int_get_ep();
- BT_ASSERT(ep);
- ok(try_add_event_class_to_trace(NULL, ep),
- "Sequence FT with non-enum length FT is invalid");
- BT_PUT(ep);
-}
-
-static
-void test_fail(void)
-{
- test_fail_unavailable_root();
- test_fail_target_is_root();
- test_fail_target_is_after_source();
- test_fail_target_is_ancestor_of_source();
- test_fail_target_is_source();
- test_fail_variant_tag_is_not_enum();
- test_fail_variant_tag_mismatch_mappings();
- test_fail_sequence_tag_is_not_int();
-}
-
-int main(void)
-{
- plan_no_plan();
-
- test_pass();
- test_fail();
-
- return 0;
-}
#include <babeltrace/graph/connection.h>
#include <babeltrace/graph/graph.h>
#include <babeltrace/graph/notification-event.h>
-#include <babeltrace/graph/notification-inactivity.h>
#include <babeltrace/graph/notification-iterator.h>
#include <babeltrace/graph/notification-packet.h>
#include <babeltrace/graph/notification-stream.h>
enum test_event_type {
TEST_EV_TYPE_NOTIF_UNEXPECTED,
TEST_EV_TYPE_NOTIF_EVENT,
- TEST_EV_TYPE_NOTIF_INACTIVITY,
TEST_EV_TYPE_NOTIF_STREAM_BEGIN,
TEST_EV_TYPE_NOTIF_PACKET_BEGIN,
TEST_EV_TYPE_NOTIF_PACKET_END,
SEQ_EVENT_STREAM1_PACKET2 = -15,
SEQ_EVENT_STREAM2_PACKET1 = -16,
SEQ_EVENT_STREAM2_PACKET2 = -17,
- SEQ_INACTIVITY = -18,
};
struct src_iter_user_data {
case TEST_EV_TYPE_NOTIF_EVENT:
fprintf(fp, "TEST_EV_TYPE_NOTIF_EVENT");
break;
- case TEST_EV_TYPE_NOTIF_INACTIVITY:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_INACTIVITY");
- break;
case TEST_EV_TYPE_NOTIF_STREAM_BEGIN:
fprintf(fp, "TEST_EV_TYPE_NOTIF_STREAM_BEGIN");
break;
static
void init_static_data(void)
{
- int ret;
struct bt_trace *trace;
- struct bt_field_type *empty_struct_ft;
/* Test events */
test_events = g_array_new(FALSE, TRUE, sizeof(struct test_event));
BT_ASSERT(test_events);
/* Metadata */
- empty_struct_ft = bt_field_type_structure_create();
- BT_ASSERT(empty_struct_ft);
trace = bt_trace_create();
BT_ASSERT(trace);
- ret = bt_trace_set_packet_header_field_type(trace, empty_struct_ft);
- BT_ASSERT(ret == 0);
- src_stream_class = bt_stream_class_create("my-stream-class");
+ src_stream_class = bt_stream_class_create(trace);
BT_ASSERT(src_stream_class);
- ret = bt_stream_class_set_packet_context_field_type(src_stream_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_header_field_type(src_stream_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_context_field_type(src_stream_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- src_event_class = bt_event_class_create("my-event-class");
- ret = bt_event_class_set_context_field_type(src_event_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_event_class_set_payload_field_type(src_event_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_add_event_class(src_stream_class,
- src_event_class);
- BT_ASSERT(ret == 0);
- ret = bt_trace_add_stream_class(trace, src_stream_class);
- BT_ASSERT(ret == 0);
- src_stream1 = bt_stream_create(src_stream_class, "stream-1", 0);
+ src_event_class = bt_event_class_create(src_stream_class);
+ BT_ASSERT(src_event_class);
+ src_stream1 = bt_stream_create(src_stream_class);
BT_ASSERT(src_stream1);
- src_stream2 = bt_stream_create(src_stream_class, "stream-2", 1);
+ src_stream2 = bt_stream_create(src_stream_class);
BT_ASSERT(src_stream2);
- src_stream1_packet1 = bt_packet_create(src_stream1,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
+ src_stream1_packet1 = bt_packet_create(src_stream1);
BT_ASSERT(src_stream1_packet1);
- src_stream1_packet2 = bt_packet_create(src_stream1,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
+ src_stream1_packet2 = bt_packet_create(src_stream1);
BT_ASSERT(src_stream1_packet2);
- src_stream2_packet1 = bt_packet_create(src_stream2,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
+ src_stream2_packet1 = bt_packet_create(src_stream2);
BT_ASSERT(src_stream2_packet1);
- src_stream2_packet2 = bt_packet_create(src_stream2,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
+ src_stream2_packet2 = bt_packet_create(src_stream2);
BT_ASSERT(src_stream2_packet2);
if (debug) {
}
bt_put(trace);
- bt_put(empty_struct_ft);
}
static
struct bt_packet *event_packet = NULL;
switch (user_data->seq[user_data->at]) {
- case SEQ_INACTIVITY:
- *notif = bt_notification_inactivity_create(cur_notif_iter);
- break;
case SEQ_STREAM1_BEGIN:
*notif = bt_notification_stream_begin_create(cur_notif_iter,
src_stream1);
BT_ASSERT(test_event.packet);
break;
}
- case BT_NOTIFICATION_TYPE_INACTIVITY:
- test_event.type = TEST_EV_TYPE_NOTIF_INACTIVITY;
- break;
case BT_NOTIFICATION_TYPE_STREAM_BEGIN:
test_event.type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN;
test_event.stream =
#include <babeltrace/assert-internal.h>
#include "common.h"
-#define NR_TESTS 41
+#define NR_TESTS 37
struct user {
struct bt_trace *tc;
struct bt_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL;
structure = bt_field_type_structure_create();
- if (!structure) {
- goto error;
- }
-
- ui8 = bt_field_type_integer_create(8);
- if (!ui8) {
- diag("Failed to create uint8_t type");
- goto error;
- }
- ret = bt_field_type_structure_add_field(structure, ui8,
- "payload_8");
- if (ret) {
- diag("Failed to add uint8_t to structure");
- goto error;
- }
- ui16 = bt_field_type_integer_create(16);
- if (!ui16) {
- diag("Failed to create uint16_t type");
- goto error;
- }
- ret = bt_field_type_structure_add_field(structure, ui16,
- "payload_16");
- if (ret) {
- diag("Failed to add uint16_t to structure");
- goto error;
- }
- ui32 = bt_field_type_integer_create(32);
- if (!ui32) {
- diag("Failed to create uint32_t type");
- goto error;
- }
- ret = bt_field_type_structure_add_field(structure, ui32,
- "payload_32");
- if (ret) {
- diag("Failed to add uint32_t to structure");
- goto error;
- }
-end:
+ BT_ASSERT(structure);
+ ui8 = bt_field_type_unsigned_integer_create();
+ BT_ASSERT(ui8);
+ ret = bt_field_type_integer_set_field_value_range(ui8, 8);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(structure,
+ "payload_8", ui8);
+ BT_ASSERT(ret == 0);
+ ui16 = bt_field_type_unsigned_integer_create();
+ BT_ASSERT(ui16);
+ ret = bt_field_type_integer_set_field_value_range(ui16, 16);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(structure,
+ "payload_16", ui16);
+ BT_ASSERT(ret == 0);
+ ui32 = bt_field_type_unsigned_integer_create();
+ BT_ASSERT(ui32);
+ ret = bt_field_type_integer_set_field_value_range(ui32, 32);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(structure,
+ "payload_32", ui32);
+ BT_ASSERT(ret == 0);
BT_PUT(ui8);
BT_PUT(ui16);
BT_PUT(ui32);
return structure;
-error:
- BT_PUT(structure);
- goto end;
}
static struct bt_ctf_field_type *create_writer_integer_struct(void)
struct bt_ctf_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL;
structure = bt_ctf_field_type_structure_create();
- if (!structure) {
- goto error;
- }
-
+ BT_ASSERT(structure);
ui8 = bt_ctf_field_type_integer_create(8);
- if (!ui8) {
- diag("Failed to create uint8_t type");
- goto error;
- }
+ BT_ASSERT(ui8);
ret = bt_ctf_field_type_structure_add_field(structure, ui8,
"payload_8");
- if (ret) {
- diag("Failed to add uint8_t to structure");
- goto error;
- }
+ BT_ASSERT(ret == 0);
ui16 = bt_ctf_field_type_integer_create(16);
- if (!ui16) {
- diag("Failed to create uint16_t type");
- goto error;
- }
+ BT_ASSERT(ui16);
ret = bt_ctf_field_type_structure_add_field(structure, ui16,
"payload_16");
- if (ret) {
- diag("Failed to add uint16_t to structure");
- goto error;
- }
+ BT_ASSERT(ret == 0);
ui32 = bt_ctf_field_type_integer_create(32);
- if (!ui32) {
- diag("Failed to create uint32_t type");
- goto error;
- }
+ BT_ASSERT(ui32);
ret = bt_ctf_field_type_structure_add_field(structure, ui32,
"payload_32");
- if (ret) {
- diag("Failed to add uint32_t to structure");
- goto error;
- }
-end:
+ BT_ASSERT(ret == 0);
BT_PUT(ui8);
BT_PUT(ui16);
BT_PUT(ui32);
return structure;
-error:
- BT_PUT(structure);
- goto end;
}
/**
* - uint16_t payload_16;
* - uint32_t payload_32;
*/
-static struct bt_event_class *create_simple_event(const char *name)
+static struct bt_event_class *create_simple_event(struct bt_stream_class *sc,
+ const char *name)
{
int ret;
struct bt_event_class *event = NULL;
struct bt_field_type *payload = NULL;
BT_ASSERT(name);
- event = bt_event_class_create(name);
- if (!event) {
- diag("Failed to create simple event");
- goto error;
- }
-
+ event = bt_event_class_create(sc);
+ BT_ASSERT(event);
+ ret = bt_event_class_set_name(event, name);
+ BT_ASSERT(ret == 0);
payload = create_integer_struct();
- if (!payload) {
- diag("Failed to initialize integer structure");
- goto error;
- }
-
+ BT_ASSERT(payload);
ret = bt_event_class_set_payload_field_type(event, payload);
- if (ret) {
- diag("Failed to set simple event payload");
- goto error;
- }
-end:
+ BT_ASSERT(ret == 0);
BT_PUT(payload);
return event;
-error:
- BT_PUT(event);
- goto end;;
}
/**
* - uint16_t payload_16;
* - uint32_t payload_32;
*/
-static struct bt_event_class *create_complex_event(const char *name)
+static struct bt_event_class *create_complex_event(struct bt_stream_class *sc,
+ const char *name)
{
int ret;
struct bt_event_class *event = NULL;
struct bt_field_type *inner = NULL, *outer = NULL;
BT_ASSERT(name);
- event = bt_event_class_create(name);
- if (!event) {
- diag("Failed to create complex event");
- goto error;
- }
-
+ event = bt_event_class_create(sc);
+ BT_ASSERT(event);
+ ret = bt_event_class_set_name(event, name);
+ BT_ASSERT(ret == 0);
outer = create_integer_struct();
- if (!outer) {
- diag("Failed to initialize integer structure");
- goto error;
- }
-
+ BT_ASSERT(outer);
inner = create_integer_struct();
- if (!inner) {
- diag("Failed to initialize integer structure");
- goto error;
- }
-
- ret = bt_field_type_structure_add_field(outer, inner,
- "payload_struct");
- if (ret) {
- diag("Failed to add inner structure to outer structure");
- goto error;
- }
-
+ BT_ASSERT(inner);
+ ret = bt_field_type_structure_append_member(outer,
+ "payload_struct", inner);
+ BT_ASSERT(ret == 0);
ret = bt_event_class_set_payload_field_type(event, outer);
- if (ret) {
- diag("Failed to set complex event payload");
- goto error;
- }
-end:
+ BT_ASSERT(ret == 0);
BT_PUT(inner);
BT_PUT(outer);
return event;
-error:
- BT_PUT(event);
- goto end;;
}
static void set_stream_class_field_types(
packet_context_type = bt_field_type_structure_create();
BT_ASSERT(packet_context_type);
- ft = bt_field_type_integer_create(32);
+ ft = bt_field_type_unsigned_integer_create();
BT_ASSERT(ft);
- ret = bt_field_type_structure_add_field(packet_context_type,
- ft, "packet_size");
+ ret = bt_field_type_integer_set_field_value_range(ft, 32);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(packet_context_type,
+ "packet_size", ft);
BT_ASSERT(ret == 0);
bt_put(ft);
- ft = bt_field_type_integer_create(32);
+ ft = bt_field_type_unsigned_integer_create();
BT_ASSERT(ft);
- ret = bt_field_type_structure_add_field(packet_context_type,
- ft, "content_size");
+ ret = bt_field_type_integer_set_field_value_range(ft, 32);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(packet_context_type,
+ "content_size", ft);
BT_ASSERT(ret == 0);
bt_put(ft);
-
event_header_type = bt_field_type_structure_create();
BT_ASSERT(event_header_type);
- ft = bt_field_type_integer_create(32);
+ ft = bt_field_type_unsigned_integer_create();
BT_ASSERT(ft);
- ret = bt_field_type_structure_add_field(event_header_type,
- ft, "id");
+ ret = bt_field_type_integer_set_field_value_range(ft, 32);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(event_header_type,
+ "id", ft);
BT_ASSERT(ret == 0);
bt_put(ft);
-
ret = bt_stream_class_set_packet_context_field_type(stream_class,
packet_context_type);
BT_ASSERT(ret == 0);
ret = bt_stream_class_set_event_header_field_type(stream_class,
event_header_type);
BT_ASSERT(ret == 0);
-
bt_put(packet_context_type);
bt_put(event_header_type);
}
-static struct bt_stream_class *create_sc1(void)
+static void create_sc1(struct bt_trace *trace)
{
int ret;
struct bt_event_class *ec1 = NULL, *ec2 = NULL;
struct bt_stream_class *sc1 = NULL, *ret_stream = NULL;
- sc1 = bt_stream_class_create("sc1");
- if (!sc1) {
- diag("Failed to create Stream Class");
- goto error;
- }
-
+ sc1 = bt_stream_class_create(trace);
+ BT_ASSERT(sc1);
+ ret = bt_stream_class_set_name(sc1, "sc1");
+ BT_ASSERT(ret == 0);
set_stream_class_field_types(sc1);
- ec1 = create_complex_event("ec1");
- if (!ec1) {
- diag("Failed to create complex event EC1");
- goto error;
- }
- ret = bt_stream_class_add_event_class(sc1, ec1);
- if (ret) {
- diag("Failed to add EC1 to SC1");
- goto error;
- }
-
- ec2 = create_simple_event("ec2");
- if (!ec2) {
- diag("Failed to create simple event EC2");
- goto error;
- }
- ret = bt_stream_class_add_event_class(sc1, ec2);
- if (ret) {
- diag("Failed to add EC1 to SC1");
- goto error;
- }
-
- ret_stream = bt_event_class_get_stream_class(ec1);
- ok(ret_stream == sc1, "Get parent stream SC1 from EC1");
- BT_PUT(ret_stream);
-
- ret_stream = bt_event_class_get_stream_class(ec2);
- ok(ret_stream == sc1, "Get parent stream SC1 from EC2");
-end:
- BT_PUT(ret_stream);
+ ec1 = create_complex_event(sc1, "ec1");
+ BT_ASSERT(ec1);
+ ec2 = create_simple_event(sc1, "ec2");
+ BT_ASSERT(ec2);
+ ret_stream = bt_event_class_borrow_stream_class(ec1);
+ ok(ret_stream == sc1, "Borrow parent stream SC1 from EC1");
+ ret_stream = bt_event_class_borrow_stream_class(ec2);
+ ok(ret_stream == sc1, "Borrow parent stream SC1 from EC2");
BT_PUT(ec1);
BT_PUT(ec2);
- return sc1;
-error:
BT_PUT(sc1);
- goto end;
}
-static struct bt_stream_class *create_sc2(void)
+static void create_sc2(struct bt_trace *trace)
{
int ret;
struct bt_event_class *ec3 = NULL;
struct bt_stream_class *sc2 = NULL, *ret_stream = NULL;
- sc2 = bt_stream_class_create("sc2");
- if (!sc2) {
- diag("Failed to create Stream Class");
- goto error;
- }
-
+ sc2 = bt_stream_class_create(trace);
+ BT_ASSERT(sc2);
+ ret = bt_stream_class_set_name(sc2, "sc2");
+ BT_ASSERT(ret == 0);
set_stream_class_field_types(sc2);
- ec3 = create_simple_event("ec3");
- if (!ec3) {
- diag("Failed to create simple event EC3");
- goto error;
- }
- ret = bt_stream_class_add_event_class(sc2, ec3);
- if (ret) {
- diag("Failed to add EC3 to SC2");
- goto error;
- }
-
- ret_stream = bt_event_class_get_stream_class(ec3);
- ok(ret_stream == sc2, "Get parent stream SC2 from EC3");
-end:
- BT_PUT(ret_stream);
+ ec3 = create_simple_event(sc2, "ec3");
+ ret_stream = bt_event_class_borrow_stream_class(ec3);
+ ok(ret_stream == sc2, "Borrow parent stream SC2 from EC3");
BT_PUT(ec3);
- return sc2;
-error:
BT_PUT(sc2);
- goto end;
}
static void set_trace_packet_header(struct bt_trace *trace)
packet_header_type = bt_field_type_structure_create();
BT_ASSERT(packet_header_type);
- ft = bt_field_type_integer_create(32);
+ ft = bt_field_type_unsigned_integer_create();
BT_ASSERT(ft);
- ret = bt_field_type_structure_add_field(packet_header_type,
- ft, "stream_id");
+ ret = bt_field_type_integer_set_field_value_range(ft, 32);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_structure_append_member(packet_header_type,
+ "stream_id", ft);
BT_ASSERT(ret == 0);
bt_put(ft);
-
ret = bt_trace_set_packet_header_field_type(trace,
packet_header_type);
BT_ASSERT(ret == 0);
static struct bt_trace *create_tc1(void)
{
- int ret;
struct bt_trace *tc1 = NULL;
- struct bt_stream_class *sc1 = NULL, *sc2 = NULL;
tc1 = bt_trace_create();
- if (!tc1) {
- diag("bt_trace_create returned NULL");
- goto error;
- }
-
+ BT_ASSERT(tc1);
set_trace_packet_header(tc1);
- sc1 = create_sc1();
- ok(sc1, "Create SC1");
- if (!sc1) {
- goto error;
- }
- ret = bt_trace_add_stream_class(tc1, sc1);
- ok(!ret, "Add SC1 to TC1");
- if (ret) {
- goto error;
- }
-
- sc2 = create_sc2();
- ok(sc2, "Create SC2");
- if (!sc2) {
- goto error;
- }
- ret = bt_trace_add_stream_class(tc1, sc2);
- ok(!ret, "Add SC2 to TC1");
- if (ret) {
- goto error;
- }
-end:
- BT_PUT(sc1);
- BT_PUT(sc2);
+ create_sc1(tc1);
+ create_sc2(tc1);
return tc1;
-error:
- BT_PUT(tc1);
- goto end;
}
static void init_weak_refs(struct bt_trace *tc,
struct bt_event_class **ec3)
{
*tc1 = tc;
- *sc1 = bt_trace_get_stream_class_by_index(tc, 0);
- *sc2 = bt_trace_get_stream_class_by_index(tc, 1);
- *ec1 = bt_stream_class_get_event_class_by_index(*sc1, 0);
- *ec2 = bt_stream_class_get_event_class_by_index(*sc1, 1);
- *ec3 = bt_stream_class_get_event_class_by_index(*sc2, 0);
- bt_put(*sc1);
- bt_put(*sc2);
- bt_put(*ec1);
- bt_put(*ec2);
- bt_put(*ec3);
+ *sc1 = bt_trace_borrow_stream_class_by_index(tc, 0);
+ *sc2 = bt_trace_borrow_stream_class_by_index(tc, 1);
+ *ec1 = bt_stream_class_borrow_event_class_by_index(*sc1, 0);
+ *ec2 = bt_stream_class_borrow_event_class_by_index(*sc1, 1);
+ *ec3 = bt_stream_class_borrow_event_class_by_index(*sc2, 0);
}
static void test_example_scenario(void)
/* The only reference which exists at this point is on TC1. */
tc1 = create_tc1();
ok(tc1, "Initialize trace");
- if (!tc1) {
- return;
- }
-
+ BT_ASSERT(tc1);
init_weak_refs(tc1, &weak_tc1, &weak_sc1, &weak_sc2, &weak_ec1,
&weak_ec2, &weak_ec3);
-
ok(bt_object_get_ref_count((void *) weak_sc1) == 0,
"Initial SC1 reference count is 0");
ok(bt_object_get_ref_count((void *) weak_sc2) == 0,
"TC1 reference count is 1");
/* User A acquires a reference to SC2 from TC1. */
- user_a.sc = bt_trace_get_stream_class_by_index(user_a.tc, 1);
+ user_a.sc = bt_get(bt_trace_borrow_stream_class_by_index(user_a.tc, 1));
ok(user_a.sc, "User A acquires SC2 from TC1");
ok(bt_object_get_ref_count((void *) weak_tc1) == 2,
"TC1 reference count is 2");
"SC2 reference count is 1");
/* User A acquires a reference to EC3 from SC2. */
- user_a.ec = bt_stream_class_get_event_class_by_index(user_a.sc, 0);
+ user_a.ec = bt_get(
+ bt_stream_class_borrow_event_class_by_index(user_a.sc, 0));
ok(user_a.ec, "User A acquires EC3 from SC2");
ok(bt_object_get_ref_count((void *) weak_tc1) == 2,
"TC1 reference count is 2");
/* User C acquires a reference to EC1. */
diag("User C acquires a reference to EC1");
- user_c.ec = bt_stream_class_get_event_class_by_index(user_b.sc, 0);
+ user_c.ec = bt_get(
+ bt_stream_class_borrow_event_class_by_index(user_b.sc, 0));
ok(bt_object_get_ref_count((void *) weak_ec1) == 1,
"EC1 reference count is 1");
ok(bt_object_get_ref_count((void *) weak_sc1) == 2,
noinst_PROGRAMS =
if !ENABLE_BUILT_IN_PLUGINS
-test_utils_muxer_SOURCES = test-utils-muxer.c
-test_utils_muxer_LDADD = $(COMMON_TEST_LDADD)
-
-noinst_PROGRAMS += test-utils-muxer
-check_SCRIPTS += test-utils-muxer-complete
+# plugin tests here
endif # !ENABLE_BUILT_IN_PLUGINS
if ENABLE_DEBUG_INFO
+++ /dev/null
-/*
- * Copyright 2017 - Philippe Proulx <pproulx@efficios.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <inttypes.h>
-#include <string.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/babeltrace.h>
-#include <glib.h>
-
-#include "tap/tap.h"
-
-#define NR_TESTS 12
-
-enum test {
- TEST_NO_TS,
- TEST_NO_UPSTREAM_CONNECTION,
- TEST_SIMPLE_4_PORTS,
- TEST_4_PORTS_WITH_RETRIES,
- TEST_SINGLE_END_THEN_MULTIPLE_FULL,
- TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL,
-};
-
-enum test_event_type {
- TEST_EV_TYPE_NOTIF_UNEXPECTED,
- TEST_EV_TYPE_NOTIF_EVENT,
- TEST_EV_TYPE_NOTIF_INACTIVITY,
- TEST_EV_TYPE_NOTIF_PACKET_BEGIN,
- TEST_EV_TYPE_NOTIF_PACKET_END,
- TEST_EV_TYPE_NOTIF_STREAM_BEGIN,
- TEST_EV_TYPE_NOTIF_STREAM_END,
- TEST_EV_TYPE_AGAIN,
- TEST_EV_TYPE_END,
- TEST_EV_TYPE_SENTINEL,
-};
-
-struct test_event {
- enum test_event_type type;
- int64_t ts_ns;
-};
-
-struct source_muxer_sink {
- struct bt_component *source;
- struct bt_component *muxer;
- struct bt_component *sink;
-};
-
-struct graph_listener_data {
- struct bt_graph *graph;
- struct bt_component *source;
- struct bt_component *muxer;
- struct bt_component *sink;
-};
-
-static bool debug = false;
-static enum test current_test;
-static GArray *test_events;
-static struct bt_graph *graph;
-static struct bt_private_connection_private_notification_iterator *cur_notif_iter;
-static struct bt_clock_class *src_clock_class;
-static struct bt_stream_class *src_stream_class;
-static struct bt_event_class *src_event_class;
-static struct bt_packet *src_packet0;
-static struct bt_packet *src_packet1;
-static struct bt_packet *src_packet2;
-static struct bt_packet *src_packet3;
-
-enum {
- SEQ_END = -1,
- SEQ_AGAIN = -2,
- SEQ_PACKET_BEGIN = -3,
- SEQ_PACKET_END = -4,
- SEQ_STREAM_BEGIN = -5,
- SEQ_STREAM_END = -6,
-};
-
-struct src_iter_user_data {
- size_t iter_index;
- int64_t *seq;
- size_t at;
- struct bt_packet *packet;
-};
-
-struct sink_user_data {
- struct bt_notification_iterator *notif_iter;
-};
-
-static int64_t seq1[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 24, 53, 97, 105, 119, 210,
- 222, 240, 292, 317, 353, 407, 433, 473, 487, 504, 572, 615, 708,
- 766, 850, 852, 931, 951, 956, 996, SEQ_PACKET_END,
- SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq2[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 51, 59, 68, 77, 91, 121,
- 139, 170, 179, 266, 352, 454, 478, 631, 644, 668, 714, 744, 750,
- 778, 790, 836, SEQ_PACKET_END, SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq3[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 8, 71, 209, 254, 298, 320,
- 350, 393, 419, 624, 651, 678, 717, 731, 733, 788, 819, 820, 857,
- 892, 903, 944, 998, SEQ_PACKET_END, SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq4[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 41, 56, 120, 138, 154, 228,
- 471, 479, 481, 525, 591, 605, 612, 618, 632, 670, 696, 825, 863,
- 867, 871, 884, 953, 985, 999, SEQ_PACKET_END, SEQ_STREAM_END,
- SEQ_END,
-};
-
-static int64_t seq1_with_again[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 24, 53, 97, 105, 119, 210,
- SEQ_AGAIN, SEQ_AGAIN, 222, 240, 292, 317, 353, 407, 433, 473,
- 487, 504, 572, 615, 708, 766, 850, 852, 931, 951, 956, 996,
- SEQ_PACKET_END, SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq2_with_again[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 51, 59, 68, 77, 91, 121,
- 139, 170, 179, 266, 352, 454, 478, 631, 644, 668, 714, 744, 750,
- 778, 790, 836, SEQ_AGAIN, SEQ_AGAIN, SEQ_PACKET_END,
- SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq3_with_again[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 8, 71, 209, 254, 298, 320,
- 350, 393, 419, 624, 651, SEQ_AGAIN, SEQ_AGAIN, 678, 717, 731,
- 733, 788, 819, 820, 857, 892, 903, 944, 998, SEQ_PACKET_END,
- SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq4_with_again[] = {
- SEQ_AGAIN, SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 41, 56, 120, 138,
- 154, 228, 471, 479, 481, 525, 591, 605, 612, 618, 632, 670, 696,
- 825, 863, 867, 871, 884, 953, 985, 999, SEQ_PACKET_END,
- SEQ_STREAM_END, SEQ_END,
-};
-
-static int64_t seq5[] = {
- SEQ_STREAM_BEGIN, SEQ_PACKET_BEGIN, 1, 4, 189, 1001,
- SEQ_PACKET_END, SEQ_STREAM_END, SEQ_END,
-};
-
-static
-void clear_test_events(void)
-{
- g_array_set_size(test_events, 0);
-}
-
-static
-void print_test_event(FILE *fp, const struct test_event *event)
-{
- fprintf(fp, "{ type = ");
-
- switch (event->type) {
- case TEST_EV_TYPE_NOTIF_UNEXPECTED:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_UNEXPECTED");
- break;
- case TEST_EV_TYPE_NOTIF_EVENT:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_EVENT");
- break;
- case TEST_EV_TYPE_NOTIF_INACTIVITY:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_INACTIVITY");
- break;
- case TEST_EV_TYPE_NOTIF_PACKET_BEGIN:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_PACKET_BEGIN");
- break;
- case TEST_EV_TYPE_NOTIF_PACKET_END:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_PACKET_END");
- break;
- case TEST_EV_TYPE_NOTIF_STREAM_BEGIN:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_STREAM_BEGIN");
- break;
- case TEST_EV_TYPE_NOTIF_STREAM_END:
- fprintf(fp, "TEST_EV_TYPE_NOTIF_STREAM_END");
- break;
- case TEST_EV_TYPE_AGAIN:
- fprintf(fp, "TEST_EV_TYPE_AGAIN");
- break;
- case TEST_EV_TYPE_END:
- fprintf(fp, "TEST_EV_TYPE_END");
- break;
- case TEST_EV_TYPE_SENTINEL:
- fprintf(fp, "TEST_EV_TYPE_SENTINEL");
- break;
- default:
- fprintf(fp, "(UNKNOWN)");
- break;
- }
-
- switch (event->type) {
- case TEST_EV_TYPE_NOTIF_EVENT:
- case TEST_EV_TYPE_NOTIF_INACTIVITY:
- fprintf(fp, ", ts-ns = %" PRId64, event->ts_ns);
- default:
- break;
- }
-
- fprintf(fp, " }");
-}
-
-static
-void append_test_event(struct test_event *event)
-{
- g_array_append_val(test_events, *event);
-}
-
-static
-bool compare_single_test_events(const struct test_event *ev_a,
- const struct test_event *ev_b)
-{
- if (debug) {
- fprintf(stderr, ":: Comparing test events: ");
- print_test_event(stderr, ev_a);
- fprintf(stderr, " vs. ");
- print_test_event(stderr, ev_b);
- fprintf(stderr, "\n");
- }
-
- if (ev_a->type != ev_b->type) {
- return false;
- }
-
- switch (ev_a->type) {
- case TEST_EV_TYPE_NOTIF_EVENT:
- case TEST_EV_TYPE_NOTIF_INACTIVITY:
- if (ev_a->ts_ns != ev_b->ts_ns) {
- return false;
- }
- break;
- default:
- break;
- }
-
- return true;
-}
-
-static
-bool compare_test_events(const struct test_event *expected_events)
-{
- const struct test_event *expected_event = expected_events;
- size_t i = 0;
-
- BT_ASSERT(expected_events);
-
- while (true) {
- const struct test_event *event;
-
- if (expected_event->type == TEST_EV_TYPE_SENTINEL) {
- break;
- }
-
- if (i >= test_events->len) {
- return false;
- }
-
- event = &g_array_index(test_events, struct test_event, i);
-
- if (!compare_single_test_events(event, expected_event)) {
- return false;
- }
-
- i++;
- expected_event++;
- }
-
- if (i != test_events->len) {
- if (debug) {
- fprintf(stderr, ":: Length mismatch\n");
- }
-
- return false;
- }
-
- return true;
-}
-
-static
-void init_static_data(void)
-{
- int ret;
- struct bt_trace *trace;
- struct bt_stream *stream;
- struct bt_field_type *empty_struct_ft;
- struct bt_field_type *eh_ft;
- struct bt_field_type *eh_ts_ft;
-
- /* Test events */
- test_events = g_array_new(FALSE, TRUE, sizeof(struct test_event));
- BT_ASSERT(test_events);
-
- /* Metadata */
- empty_struct_ft = bt_field_type_structure_create();
- BT_ASSERT(empty_struct_ft);
- src_clock_class = bt_clock_class_create("my-clock", 1000000000);
- BT_ASSERT(src_clock_class);
- trace = bt_trace_create();
- BT_ASSERT(trace);
- ret = bt_trace_set_native_byte_order(trace,
- BT_BYTE_ORDER_LITTLE_ENDIAN);
- BT_ASSERT(ret == 0);
- ret = bt_trace_set_packet_header_field_type(trace, empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_clock_class_set_is_absolute(src_clock_class, 1);
- BT_ASSERT(ret == 0);
- ret = bt_trace_add_clock_class(trace, src_clock_class);
- BT_ASSERT(ret == 0);
- src_stream_class = bt_stream_class_create("my-stream-class");
- BT_ASSERT(src_stream_class);
- ret = bt_stream_class_set_packet_context_field_type(src_stream_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- eh_ft = bt_field_type_structure_create();
- BT_ASSERT(eh_ft);
- eh_ts_ft = bt_field_type_integer_create(64);
- BT_ASSERT(eh_ts_ft);
- ret = bt_field_type_structure_add_field(eh_ft, eh_ts_ft, "ts");
- BT_ASSERT(ret == 0);
- ret = bt_field_type_integer_set_mapped_clock_class(eh_ts_ft,
- src_clock_class);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_header_field_type(src_stream_class,
- eh_ft);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_set_event_context_field_type(src_stream_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- src_event_class = bt_event_class_create("my-event-class");
- ret = bt_event_class_set_context_field_type(src_event_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_event_class_set_context_field_type(src_event_class,
- empty_struct_ft);
- BT_ASSERT(ret == 0);
- ret = bt_stream_class_add_event_class(src_stream_class,
- src_event_class);
- BT_ASSERT(ret == 0);
- ret = bt_trace_add_stream_class(trace, src_stream_class);
- BT_ASSERT(ret == 0);
- stream = bt_stream_create(src_stream_class, "stream0", 0);
- BT_ASSERT(stream);
- src_packet0 = bt_packet_create(stream,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
- BT_ASSERT(src_packet0);
- bt_put(stream);
- stream = bt_stream_create(src_stream_class, "stream1", 1);
- BT_ASSERT(stream);
- src_packet1 = bt_packet_create(stream,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
- BT_ASSERT(src_packet0);
- bt_put(stream);
- stream = bt_stream_create(src_stream_class, "stream2", 2);
- BT_ASSERT(stream);
- src_packet2 = bt_packet_create(stream,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
- BT_ASSERT(src_packet0);
- bt_put(stream);
- stream = bt_stream_create(src_stream_class, "stream3", 3);
- BT_ASSERT(stream);
- src_packet3 = bt_packet_create(stream,
- BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, NULL);
- BT_ASSERT(src_packet0);
- bt_put(stream);
-
- bt_put(trace);
- bt_put(empty_struct_ft);
- bt_put(eh_ft);
- bt_put(eh_ts_ft);
-}
-
-static
-void fini_static_data(void)
-{
- /* Test events */
- g_array_free(test_events, TRUE);
-
- /* Metadata */
- bt_put(src_clock_class);
- bt_put(src_stream_class);
- bt_put(src_event_class);
- bt_put(src_packet0);
- bt_put(src_packet1);
- bt_put(src_packet2);
- bt_put(src_packet3);
-}
-
-static
-void src_iter_finalize(
- struct bt_private_connection_private_notification_iterator *private_notification_iterator)
-{
- struct src_iter_user_data *user_data =
- bt_private_connection_private_notification_iterator_get_user_data(
- private_notification_iterator);
-
- if (user_data) {
- g_free(user_data);
- }
-}
-
-static
-enum bt_notification_iterator_status src_iter_init(
- struct bt_private_connection_private_notification_iterator *priv_notif_iter,
- struct bt_private_port *private_port)
-{
- struct src_iter_user_data *user_data =
- g_new0(struct src_iter_user_data, 1);
- struct bt_port *port = bt_port_borrow_from_private(private_port);
- const char *port_name;
- int ret;
-
- BT_ASSERT(user_data);
- BT_ASSERT(port);
- ret = bt_private_connection_private_notification_iterator_set_user_data(priv_notif_iter,
- user_data);
- BT_ASSERT(ret == 0);
- port_name = bt_port_get_name(port);
- BT_ASSERT(port_name);
- user_data->iter_index = port_name[3] - '0';
-
- switch (user_data->iter_index) {
- case 0:
- user_data->packet = src_packet0;
- break;
- case 1:
- user_data->packet = src_packet1;
- break;
- case 2:
- user_data->packet = src_packet2;
- break;
- case 3:
- user_data->packet = src_packet3;
- break;
- default:
- abort();
- }
-
- switch (current_test) {
- case TEST_NO_TS:
- if (user_data->iter_index == 1) {
- user_data->seq = seq5;
- }
- break;
- case TEST_SIMPLE_4_PORTS:
- if (user_data->iter_index == 0) {
- user_data->seq = seq1;
- } else if (user_data->iter_index == 1) {
- user_data->seq = seq2;
- } else if (user_data->iter_index == 2) {
- user_data->seq = seq3;
- } else {
- user_data->seq = seq4;
- }
- break;
- case TEST_4_PORTS_WITH_RETRIES:
- if (user_data->iter_index == 0) {
- user_data->seq = seq1_with_again;
- } else if (user_data->iter_index == 1) {
- user_data->seq = seq2_with_again;
- } else if (user_data->iter_index == 2) {
- user_data->seq = seq3_with_again;
- } else {
- user_data->seq = seq4_with_again;
- }
- break;
- case TEST_SINGLE_END_THEN_MULTIPLE_FULL:
- case TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL:
- if (user_data->iter_index == 0) {
- /* Ignore: this iterator only returns END */
- } else if (user_data->iter_index == 1) {
- user_data->seq = seq2;
- } else {
- user_data->seq = seq3;
- }
- break;
- default:
- abort();
- }
-
- return BT_NOTIFICATION_ITERATOR_STATUS_OK;
-}
-
-static
-struct bt_notification *src_create_event_notif(struct bt_packet *packet,
- int64_t ts_ns)
-{
- int ret;
- struct bt_event *event;
- struct bt_notification *notif;
- struct bt_field *field;
-
- notif = bt_notification_event_create(cur_notif_iter,
- src_event_class, packet);
- BT_ASSERT(notif);
- event = bt_notification_event_borrow_event(notif);
- BT_ASSERT(event);
- field = bt_event_borrow_header(event);
- BT_ASSERT(field);
- field = bt_field_structure_borrow_field_by_name(field, "ts");
- BT_ASSERT(field);
- ret = bt_field_integer_unsigned_set_value(field, (uint64_t) ts_ns);
- BT_ASSERT(ret == 0);
-
- if (ts_ns != UINT64_C(-1)) {
- ret = bt_event_set_clock_value(event, src_clock_class, (uint64_t) ts_ns,
- BT_TRUE);
- BT_ASSERT(ret == 0);
- }
-
- return notif;
-}
-
-static
-enum bt_notification_iterator_status src_iter_next_seq(
- struct src_iter_user_data *user_data,
- bt_notification_array notifs)
-{
- enum bt_notification_iterator_status status =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- int64_t cur_ts_ns;
- struct bt_stream *stream;
-
- BT_ASSERT(user_data->seq);
- cur_ts_ns = user_data->seq[user_data->at];
-
- switch (cur_ts_ns) {
- case SEQ_END:
- status = BT_NOTIFICATION_ITERATOR_STATUS_END;
- break;
- case SEQ_AGAIN:
- status = BT_NOTIFICATION_ITERATOR_STATUS_AGAIN;
- break;
- case SEQ_PACKET_BEGIN:
- notifs[0] = bt_notification_packet_begin_create(cur_notif_iter,
- user_data->packet);
- BT_ASSERT(notifs[0]);
- break;
- case SEQ_PACKET_END:
- notifs[0] = bt_notification_packet_end_create(cur_notif_iter,
- user_data->packet);
- BT_ASSERT(notifs[0]);
- break;
- case SEQ_STREAM_BEGIN:
- stream = bt_packet_get_stream(user_data->packet);
- notifs[0] = bt_notification_stream_begin_create(cur_notif_iter,
- stream);
- BT_ASSERT(notifs[0]);
- bt_put(stream);
- break;
- case SEQ_STREAM_END:
- stream = bt_packet_get_stream(user_data->packet);
- notifs[0] = bt_notification_stream_end_create(cur_notif_iter,
- stream);
- BT_ASSERT(notifs[0]);
- bt_put(stream);
- break;
- default:
- {
- notifs[0] = src_create_event_notif(user_data->packet,
- cur_ts_ns);
- BT_ASSERT(notifs[0]);
- break;
- }
- }
-
- if (status != BT_NOTIFICATION_ITERATOR_STATUS_END) {
- user_data->at++;
- }
-
- return status;
-}
-
-static
-enum bt_notification_iterator_status src_iter_next(
- struct bt_private_connection_private_notification_iterator *priv_iterator,
- bt_notification_array notifs, uint64_t capacity,
- uint64_t *count)
-{
- enum bt_notification_iterator_status status =
- BT_NOTIFICATION_ITERATOR_STATUS_OK;
- struct src_iter_user_data *user_data =
- bt_private_connection_private_notification_iterator_get_user_data(priv_iterator);
- struct bt_private_component *private_component =
- bt_private_connection_private_notification_iterator_get_private_component(priv_iterator);
- struct bt_stream *stream;
- int ret;
-
- BT_ASSERT(user_data);
- BT_ASSERT(private_component);
- cur_notif_iter = priv_iterator;
-
- /*
- * We can always set it to 1: it's not going to be considered
- * anyway if the status is not
- * BT_NOTIFICATION_ITERATOR_STATUS_OK.
- */
- *count = 1;
-
- switch (current_test) {
- case TEST_NO_TS:
- if (user_data->iter_index == 0) {
- if (user_data->at == 0) {
- stream = bt_packet_get_stream(user_data->packet);
- notifs[0] =
- bt_notification_stream_begin_create(
- cur_notif_iter, stream);
- bt_put(stream);
- BT_ASSERT(notifs[0]);
- } else if (user_data->at == 1) {
- notifs[0] =
- bt_notification_packet_begin_create(
- cur_notif_iter,
- user_data->packet);
- BT_ASSERT(notifs[0]);
- } else if (user_data->at < 7) {
- notifs[0] =
- src_create_event_notif(
- user_data->packet, UINT64_C(-1));
- BT_ASSERT(notifs[0]);
- } else if (user_data->at == 7) {
- notifs[0] =
- bt_notification_packet_end_create(
- cur_notif_iter,
- user_data->packet);
- BT_ASSERT(notifs[0]);
- } else if (user_data->at == 8) {
- stream = bt_packet_get_stream(user_data->packet);
- notifs[0] =
- bt_notification_stream_end_create(
- cur_notif_iter, stream);
- bt_put(stream);
- BT_ASSERT(notifs[0]);
- } else {
- status =
- BT_NOTIFICATION_ITERATOR_STATUS_END;
- }
-
- user_data->at++;
- } else {
- status = src_iter_next_seq(user_data, notifs);
- }
- break;
- case TEST_SIMPLE_4_PORTS:
- case TEST_4_PORTS_WITH_RETRIES:
- status = src_iter_next_seq(user_data, notifs);
- break;
- case TEST_SINGLE_END_THEN_MULTIPLE_FULL:
- if (user_data->iter_index == 0) {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out1", NULL, NULL);
- BT_ASSERT(ret == 0);
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out2", NULL, NULL);
- BT_ASSERT(ret == 0);
- status = BT_NOTIFICATION_ITERATOR_STATUS_END;
- } else {
- status = src_iter_next_seq(user_data, notifs);
- }
- break;
- case TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL:
- if (user_data->iter_index == 0) {
- if (user_data->at == 0) {
- status = BT_NOTIFICATION_ITERATOR_STATUS_AGAIN;
- user_data->at++;
- } else {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out1", NULL, NULL);
- BT_ASSERT(ret == 0);
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out2", NULL, NULL);
- BT_ASSERT(ret == 0);
- status = BT_NOTIFICATION_ITERATOR_STATUS_END;
- }
- } else {
- status = src_iter_next_seq(user_data, notifs);
- }
- break;
- default:
- abort();
- }
-
- bt_put(private_component);
- return status;
-}
-
-static
-enum bt_component_status src_init(
- struct bt_private_component *private_component,
- struct bt_value *params, void *init_method_data)
-{
- int ret;
- size_t nb_ports;
-
- switch (current_test) {
- case TEST_NO_TS:
- nb_ports = 2;
- break;
- case TEST_SINGLE_END_THEN_MULTIPLE_FULL:
- case TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL:
- nb_ports = 1;
- break;
- default:
- nb_ports = 4;
- break;
- }
-
- if (nb_ports >= 1) {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out0", NULL, NULL);
- BT_ASSERT(ret == 0);
- }
-
- if (nb_ports >= 2) {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out1", NULL, NULL);
- BT_ASSERT(ret == 0);
- }
-
- if (nb_ports >= 3) {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out2", NULL, NULL);
- BT_ASSERT(ret == 0);
- }
-
- if (nb_ports >= 4) {
- ret = bt_private_component_source_add_output_private_port(
- private_component, "out3", NULL, NULL);
- BT_ASSERT(ret == 0);
- }
-
- return BT_COMPONENT_STATUS_OK;
-}
-
-static
-void src_finalize(struct bt_private_component *private_component)
-{
-}
-
-static
-void append_test_event_from_notification(struct bt_notification *notification)
-{
- int ret;
- struct test_event test_event;
- struct bt_clock_value *cv;
-
- switch (bt_notification_get_type(notification)) {
- case BT_NOTIFICATION_TYPE_EVENT:
- {
- struct bt_event *event;
-
- test_event.type = TEST_EV_TYPE_NOTIF_EVENT;
- event = bt_notification_event_borrow_event(notification);
- BT_ASSERT(event);
- cv = bt_event_borrow_default_clock_value(event);
-
- if (cv) {
- ret = bt_clock_value_get_value_ns_from_epoch(
- cv, &test_event.ts_ns);
- BT_ASSERT(ret == 0);
- } else {
- test_event.ts_ns = -1;
- }
-
- break;
- }
- case BT_NOTIFICATION_TYPE_INACTIVITY:
- {
- test_event.type = TEST_EV_TYPE_NOTIF_INACTIVITY;
- cv = bt_notification_inactivity_borrow_default_clock_value(
- notification);
-
- if (cv) {
- ret = bt_clock_value_get_value_ns_from_epoch(
- cv, &test_event.ts_ns);
- BT_ASSERT(ret == 0);
- } else {
- test_event.ts_ns = -1;
- }
-
- break;
- }
- case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
- test_event.type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN;
- break;
- case BT_NOTIFICATION_TYPE_PACKET_END:
- test_event.type = TEST_EV_TYPE_NOTIF_PACKET_END;
- break;
- case BT_NOTIFICATION_TYPE_STREAM_BEGIN:
- test_event.type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN;
- break;
- case BT_NOTIFICATION_TYPE_STREAM_END:
- test_event.type = TEST_EV_TYPE_NOTIF_STREAM_END;
- break;
- default:
- test_event.type = TEST_EV_TYPE_NOTIF_UNEXPECTED;
- break;
- }
-
- append_test_event(&test_event);
-}
-
-static
-enum bt_component_status sink_consume(
- struct bt_private_component *priv_component)
-{
- enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
- bt_notification_array notifications = NULL;
- uint64_t count;
- struct sink_user_data *user_data =
- bt_private_component_get_user_data(priv_component);
- enum bt_notification_iterator_status it_ret;
- struct test_event test_event;
- bool do_append_test_event = true;
- uint64_t i;
-
- BT_ASSERT(user_data && user_data->notif_iter);
- it_ret = bt_private_connection_notification_iterator_next(
- user_data->notif_iter, ¬ifications, &count);
- if (it_ret < 0) {
- ret = BT_COMPONENT_STATUS_ERROR;
- do_append_test_event = false;
- goto end;
- }
-
- switch (it_ret) {
- case BT_NOTIFICATION_ITERATOR_STATUS_END:
- test_event.type = TEST_EV_TYPE_END;
- ret = BT_COMPONENT_STATUS_END;
- BT_PUT(user_data->notif_iter);
- goto end;
- case BT_NOTIFICATION_ITERATOR_STATUS_AGAIN:
- test_event.type = TEST_EV_TYPE_AGAIN;
- ret = BT_COMPONENT_STATUS_AGAIN;
- goto end;
- default:
- break;
- }
-
- BT_ASSERT(notifications);
-
- for (i = 0; i < count; i++) {
- append_test_event_from_notification(notifications[i]);
- bt_put(notifications[i]);
- }
-
- do_append_test_event = false;
-
-end:
- if (do_append_test_event) {
- append_test_event(&test_event);
- }
-
- return ret;
-}
-
-static
-enum bt_component_status sink_port_connected(
- struct bt_private_component *private_component,
- struct bt_private_port *self_private_port,
- struct bt_port *other_port)
-{
- struct bt_private_connection *priv_conn =
- bt_private_port_get_private_connection(self_private_port);
- struct sink_user_data *user_data = bt_private_component_get_user_data(
- private_component);
- enum bt_connection_status conn_status;
-
- BT_ASSERT(user_data);
- BT_ASSERT(priv_conn);
- conn_status = bt_private_connection_create_notification_iterator(
- priv_conn, &user_data->notif_iter);
- BT_ASSERT(conn_status == 0);
- bt_put(priv_conn);
- return BT_COMPONENT_STATUS_OK;
-}
-
-static
-enum bt_component_status sink_init(
- struct bt_private_component *private_component,
- struct bt_value *params, void *init_method_data)
-{
- struct sink_user_data *user_data = g_new0(struct sink_user_data, 1);
- int ret;
-
- BT_ASSERT(user_data);
- ret = bt_private_component_set_user_data(private_component,
- user_data);
- BT_ASSERT(ret == 0);
- ret = bt_private_component_sink_add_input_private_port(
- private_component, "in", NULL, NULL);
- BT_ASSERT(ret == 0);
- return BT_COMPONENT_STATUS_OK;
-}
-
-static
-void sink_finalize(struct bt_private_component *private_component)
-{
- struct sink_user_data *user_data = bt_private_component_get_user_data(
- private_component);
-
- if (user_data) {
- bt_put(user_data->notif_iter);
- g_free(user_data);
- }
-}
-
-static
-void create_source_muxer_sink(struct bt_graph *graph,
- struct bt_component **source,
- struct bt_component **muxer,
- struct bt_component **sink)
-{
- struct bt_component_class *src_comp_class;
- struct bt_component_class *muxer_comp_class;
- struct bt_component_class *sink_comp_class;
- int ret;
-
- /* Create source component */
- src_comp_class = bt_component_class_source_create("src", src_iter_next);
- BT_ASSERT(src_comp_class);
- ret = bt_component_class_set_init_method(src_comp_class, src_init);
- BT_ASSERT(ret == 0);
- ret = bt_component_class_set_finalize_method(src_comp_class,
- src_finalize);
- BT_ASSERT(ret == 0);
- ret = bt_component_class_source_set_notification_iterator_init_method(
- src_comp_class, src_iter_init);
- BT_ASSERT(ret == 0);
- ret = bt_component_class_source_set_notification_iterator_finalize_method(
- src_comp_class, src_iter_finalize);
- BT_ASSERT(ret == 0);
- ret = bt_graph_add_component(graph, src_comp_class, "source", NULL, source);
- BT_ASSERT(ret == 0);
-
- /* Create muxer component */
- muxer_comp_class = bt_plugin_find_component_class("utils", "muxer",
- BT_COMPONENT_CLASS_TYPE_FILTER);
- BT_ASSERT(muxer_comp_class);
- ret = bt_graph_add_component(graph, muxer_comp_class, "muxer", NULL, muxer);
- BT_ASSERT(ret == 0);
-
- /* Create sink component */
- sink_comp_class = bt_component_class_sink_create("sink", sink_consume);
- BT_ASSERT(sink_comp_class);
- ret = bt_component_class_set_init_method(sink_comp_class, sink_init);
- BT_ASSERT(ret == 0);
- ret = bt_component_class_set_finalize_method(sink_comp_class,
- sink_finalize);
- ret = bt_component_class_set_port_connected_method(sink_comp_class,
- sink_port_connected);
- BT_ASSERT(ret == 0);
- ret = bt_graph_add_component(graph, sink_comp_class, "sink", NULL, sink);
- BT_ASSERT(ret == 0);
-
- bt_put(src_comp_class);
- bt_put(muxer_comp_class);
- bt_put(sink_comp_class);
-}
-
-static
-void do_std_test(enum test test, const char *name,
- const struct test_event *expected_test_events,
- bool with_upstream)
-{
- struct bt_component *src_comp;
- struct bt_component *muxer_comp;
- struct bt_component *sink_comp;
- struct bt_port *upstream_port;
- struct bt_port *downstream_port;
- int64_t i;
- int64_t count;
- enum bt_graph_status graph_status = BT_GRAPH_STATUS_OK;
-
- clear_test_events();
- current_test = test;
- diag("test: %s", name);
- BT_ASSERT(!graph);
- graph = bt_graph_create();
- BT_ASSERT(graph);
- create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp);
-
- /* Connect source output ports to muxer input ports */
- if (with_upstream) {
- count = bt_component_source_get_output_port_count(src_comp);
- BT_ASSERT(count >= 0);
-
- for (i = 0; i < count; i++) {
- upstream_port = bt_component_source_get_output_port_by_index(
- src_comp, i);
- BT_ASSERT(upstream_port);
- downstream_port = bt_component_filter_get_input_port_by_index(
- muxer_comp, i);
- BT_ASSERT(downstream_port);
- graph_status = bt_graph_connect_ports(graph,
- upstream_port, downstream_port, NULL);
- BT_ASSERT(graph_status == 0);
- bt_put(upstream_port);
- bt_put(downstream_port);
- }
- }
-
- /* Connect muxer output port to sink input port */
- upstream_port = bt_component_filter_get_output_port_by_name(muxer_comp,
- "out");
- BT_ASSERT(upstream_port);
- downstream_port = bt_component_sink_get_input_port_by_name(sink_comp, "in");
- BT_ASSERT(downstream_port);
- graph_status = bt_graph_connect_ports(graph, upstream_port,
- downstream_port, NULL);
- BT_ASSERT(graph_status == 0);
- bt_put(upstream_port);
- bt_put(downstream_port);
-
- while (graph_status == BT_GRAPH_STATUS_OK ||
- graph_status == BT_GRAPH_STATUS_AGAIN) {
- graph_status = bt_graph_run(graph);
- }
-
- ok(graph_status == BT_GRAPH_STATUS_END, "graph finishes without any error");
- ok(compare_test_events(expected_test_events),
- "the produced sequence of test events is the expected one");
-
- bt_put(src_comp);
- bt_put(muxer_comp);
- bt_put(sink_comp);
- BT_PUT(graph);
-}
-
-static
-void test_no_ts(void)
-{
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = -1, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = -1, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = -1, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = -1, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = -1, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 1, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 4, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 189, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 1001, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- do_std_test(TEST_NO_TS, "event notifications with no time",
- expected_test_events, true);
-}
-
-static
-void test_no_upstream_connection(void)
-{
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- do_std_test(TEST_NO_UPSTREAM_CONNECTION, "no upstream connection",
- expected_test_events, false);
-}
-
-static
-void test_simple_4_ports(void)
-{
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 8 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 24 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 41 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 51 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 53 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 56 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 59 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 68 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 71 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 77 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 91 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 97 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 105 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 119 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 120 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 121 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 138 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 139 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 154 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 170 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 179 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 209 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 210 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 222 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 228 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 240 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 254 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 266 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 292 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 298 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 317 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 320 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 350 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 352 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 353 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 393 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 407 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 419 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 433 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 454 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 471 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 473 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 478 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 479 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 481 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 487 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 504 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 525 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 572 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 591 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 605 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 612 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 615 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 618 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 624 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 631 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 632 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 644 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 651 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 668 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 670 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 678 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 696 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 708 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 714 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 717 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 731 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 733 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 744 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 750 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 766 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 778 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 788 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 790 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 819 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 820 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 825 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 836 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 850 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 852 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 857 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 863 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 867 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 871 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 884 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 892 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 903 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 931 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 944 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 951 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 953 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 956 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 985 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 996 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 998 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 999 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- do_std_test(TEST_SIMPLE_4_PORTS, "simple: 4 ports without retries",
- expected_test_events, true);
-}
-
-static
-void test_4_ports_with_retries(void)
-{
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_AGAIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 8 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 24 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 41 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 51 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 53 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 56 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 59 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 68 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 71 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 77 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 91 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 97 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 105 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 119 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 120 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 121 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 138 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 139 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 154 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 170 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 179 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 209 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 210 },
- { .type = TEST_EV_TYPE_AGAIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 222 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 228 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 240 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 254 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 266 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 292 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 298 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 317 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 320 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 350 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 352 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 353 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 393 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 407 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 419 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 433 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 454 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 471 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 473 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 478 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 479 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 481 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 487 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 504 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 525 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 572 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 591 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 605 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 612 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 615 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 618 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 624 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 631 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 632 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 644 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 651 },
- { .type = TEST_EV_TYPE_AGAIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 668 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 670 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 678 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 696 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 708 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 714 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 717 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 731 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 733 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 744 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 750 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 766 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 778 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 788 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 790 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 819 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 820 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 825 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 836 },
- { .type = TEST_EV_TYPE_AGAIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 850 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 852 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 857 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 863 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 867 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 871 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 884 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 892 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 903 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 931 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 944 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 951 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 953 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 956 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 985 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 996 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 998 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 999 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- do_std_test(TEST_4_PORTS_WITH_RETRIES, "4 ports with retries",
- expected_test_events, true);
-}
-
-static
-void connect_port_to_first_avail_muxer_port(struct bt_graph *graph,
- struct bt_port *source_port,
- struct bt_component *muxer_comp)
-{
- struct bt_port *avail_muxer_port = NULL;
- int64_t i;
- int64_t count;
- enum bt_graph_status graph_status;
-
- count = bt_component_filter_get_input_port_count(muxer_comp);
- BT_ASSERT(count >= 0);
-
- for (i = 0; i < count; i++) {
- struct bt_port *muxer_port =
- bt_component_filter_get_input_port_by_index(
- muxer_comp, i);
-
- BT_ASSERT(muxer_port);
-
- if (!bt_port_is_connected(muxer_port)) {
- BT_MOVE(avail_muxer_port, muxer_port);
- break;
- } else {
- bt_put(muxer_port);
- }
- }
-
- graph_status = bt_graph_connect_ports(graph, source_port,
- avail_muxer_port, NULL);
- BT_ASSERT(graph_status == 0);
- bt_put(avail_muxer_port);
-}
-
-static
-void graph_port_added_listener_connect_to_avail_muxer_port(struct bt_port *port,
- void *data)
-{
- struct graph_listener_data *graph_listener_data = data;
- struct bt_component *comp;
-
- comp = bt_port_get_component(port);
- BT_ASSERT(comp);
-
- if (comp != graph_listener_data->source) {
- goto end;
- }
-
- connect_port_to_first_avail_muxer_port(graph_listener_data->graph,
- port, graph_listener_data->muxer);
-
-end:
- bt_put(comp);
-}
-
-static
-void test_single_end_then_multiple_full(void)
-{
- struct bt_component *src_comp;
- struct bt_component *muxer_comp;
- struct bt_component *sink_comp;
- struct bt_port *upstream_port;
- struct bt_port *downstream_port;
- int64_t i;
- int64_t count;
- int ret;
- enum bt_graph_status graph_status = BT_GRAPH_STATUS_OK;
- struct graph_listener_data graph_listener_data;
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 8 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 51 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 59 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 68 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 71 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 77 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 91 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 121 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 139 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 170 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 179 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 209 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 254 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 266 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 298 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 320 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 350 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 352 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 393 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 419 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 454 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 478 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 624 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 631 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 644 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 651 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 668 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 678 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 714 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 717 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 731 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 733 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 744 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 750 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 778 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 788 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 790 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 819 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 820 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 836 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 857 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 892 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 903 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 944 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 998 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- clear_test_events();
- current_test = TEST_SINGLE_END_THEN_MULTIPLE_FULL;
- diag("test: single end then multiple full");
- BT_ASSERT(!graph);
- graph = bt_graph_create();
- BT_ASSERT(graph);
- create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp);
- graph_listener_data.graph = graph;
- graph_listener_data.source = src_comp;
- graph_listener_data.muxer = muxer_comp;
- graph_listener_data.sink = sink_comp;
- ret = bt_graph_add_port_added_listener(graph,
- graph_port_added_listener_connect_to_avail_muxer_port, NULL,
- &graph_listener_data);
- BT_ASSERT(ret >= 0);
-
- /* Connect source output ports to muxer input ports */
- count = bt_component_source_get_output_port_count(src_comp);
- BT_ASSERT(ret == 0);
-
- for (i = 0; i < count; i++) {
- upstream_port = bt_component_source_get_output_port_by_index(
- src_comp, i);
- BT_ASSERT(upstream_port);
- connect_port_to_first_avail_muxer_port(graph,
- upstream_port, muxer_comp);
- bt_put(upstream_port);
- }
-
- /* Connect muxer output port to sink input port */
- upstream_port = bt_component_filter_get_output_port_by_name(muxer_comp,
- "out");
- BT_ASSERT(upstream_port);
- downstream_port = bt_component_sink_get_input_port_by_name(sink_comp, "in");
- BT_ASSERT(downstream_port);
- graph_status = bt_graph_connect_ports(graph, upstream_port,
- downstream_port, NULL);
- BT_ASSERT(graph_status == 0);
- bt_put(upstream_port);
- bt_put(downstream_port);
-
- while (graph_status == BT_GRAPH_STATUS_OK ||
- graph_status == BT_GRAPH_STATUS_AGAIN) {
- graph_status = bt_graph_run(graph);
- }
-
- ok(graph_status == BT_GRAPH_STATUS_END, "graph finishes without any error");
- ok(compare_test_events(expected_test_events),
- "the produced sequence of test events is the expected one");
-
- bt_put(src_comp);
- bt_put(muxer_comp);
- bt_put(sink_comp);
- BT_PUT(graph);
-}
-
-static
-void test_single_again_end_then_multiple_full(void)
-{
- struct bt_component *src_comp;
- struct bt_component *muxer_comp;
- struct bt_component *sink_comp;
- struct bt_port *upstream_port;
- struct bt_port *downstream_port;
- int64_t i;
- int64_t count;
- int ret;
- enum bt_graph_status graph_status = BT_GRAPH_STATUS_OK;
- struct graph_listener_data graph_listener_data;
- const struct test_event expected_test_events[] = {
- { .type = TEST_EV_TYPE_AGAIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 8 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 51 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 59 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 68 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 71 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 77 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 91 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 121 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 139 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 170 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 179 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 209 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 254 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 266 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 298 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 320 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 350 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 352 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 393 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 419 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 454 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 478 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 624 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 631 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 644 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 651 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 668 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 678 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 714 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 717 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 731 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 733 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 744 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 750 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 778 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 788 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 790 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 819 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 820 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 836 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 857 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 892 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 903 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 944 },
- { .type = TEST_EV_TYPE_NOTIF_EVENT, .ts_ns = 998 },
- { .type = TEST_EV_TYPE_NOTIF_PACKET_END, },
- { .type = TEST_EV_TYPE_NOTIF_STREAM_END, },
- { .type = TEST_EV_TYPE_END, },
- { .type = TEST_EV_TYPE_SENTINEL, },
- };
-
- clear_test_events();
- current_test = TEST_SINGLE_AGAIN_END_THEN_MULTIPLE_FULL;
- diag("test: single again then end then multiple full");
- BT_ASSERT(!graph);
- graph = bt_graph_create();
- BT_ASSERT(graph);
- create_source_muxer_sink(graph, &src_comp, &muxer_comp, &sink_comp);
- graph_listener_data.graph = graph;
- graph_listener_data.source = src_comp;
- graph_listener_data.muxer = muxer_comp;
- graph_listener_data.sink = sink_comp;
- ret = bt_graph_add_port_added_listener(graph,
- graph_port_added_listener_connect_to_avail_muxer_port, NULL,
- &graph_listener_data);
- BT_ASSERT(ret >= 0);
-
- /* Connect source output ports to muxer input ports */
- count = bt_component_source_get_output_port_count(src_comp);
- BT_ASSERT(ret == 0);
-
- for (i = 0; i < count; i++) {
- upstream_port = bt_component_source_get_output_port_by_index(
- src_comp, i);
- BT_ASSERT(upstream_port);
- connect_port_to_first_avail_muxer_port(graph,
- upstream_port, muxer_comp);
- bt_put(upstream_port);
- }
-
- /* Connect muxer output port to sink input port */
- upstream_port = bt_component_filter_get_output_port_by_name(muxer_comp,
- "out");
- BT_ASSERT(upstream_port);
- downstream_port = bt_component_sink_get_input_port_by_name(sink_comp, "in");
- BT_ASSERT(downstream_port);
- graph_status = bt_graph_connect_ports(graph, upstream_port,
- downstream_port, NULL);
- BT_ASSERT(graph_status == 0);
- bt_put(upstream_port);
- bt_put(downstream_port);
-
- while (graph_status == BT_GRAPH_STATUS_OK ||
- graph_status == BT_GRAPH_STATUS_AGAIN) {
- graph_status = bt_graph_run(graph);
- }
-
- ok(graph_status == BT_GRAPH_STATUS_END, "graph finishes without any error");
- ok(compare_test_events(expected_test_events),
- "the produced sequence of test events is the expected one");
-
- bt_put(src_comp);
- bt_put(muxer_comp);
- bt_put(sink_comp);
- BT_PUT(graph);
-}
-
-#define DEBUG_ENV_VAR "TEST_UTILS_MUXER_DEBUG"
-
-int main(int argc, char **argv)
-{
- if (getenv(DEBUG_ENV_VAR) && strcmp(getenv(DEBUG_ENV_VAR), "1") == 0) {
- debug = true;
- }
-
- plan_tests(NR_TESTS);
- init_static_data();
- test_no_ts();
- test_no_upstream_connection();
- test_simple_4_ports();
- test_4_ports_with_retries();
- test_single_end_then_multiple_full();
- test_single_again_end_then_multiple_full();
- fini_static_data();
- return exit_status();
-}