--- /dev/null
+/*
+ * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
+#define LTTNG_EVENT_FIELD_VALUE_INTERNAL_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <lttng/event-field-value.h>
+#include <common/dynamic-array.h>
+
+struct lttng_event_field_value {
+ enum lttng_event_field_value_type type;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT`.
+ */
+struct lttng_event_field_value_uint {
+ struct lttng_event_field_value parent;
+ uint64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT`.
+ */
+struct lttng_event_field_value_int {
+ struct lttng_event_field_value parent;
+ int64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` and
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM` (base).
+ */
+struct lttng_event_field_value_enum {
+ struct lttng_event_field_value parent;
+
+ /*
+ * Array of `char *` (owned by this).
+ */
+ struct lttng_dynamic_pointer_array labels;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM`.
+ */
+struct lttng_event_field_value_enum_uint {
+ struct lttng_event_field_value_enum parent;
+ uint64_t val;
+};
+
+/*
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ */
+struct lttng_event_field_value_enum_int {
+ struct lttng_event_field_value_enum parent;
+ int64_t val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_REAL` */
+struct lttng_event_field_value_real {
+ struct lttng_event_field_value parent;
+ double val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
+struct lttng_event_field_value_string {
+ struct lttng_event_field_value parent;
+
+ /* Owned by this */
+ char *val;
+};
+
+/* `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING` */
+struct lttng_event_field_value_array {
+ struct lttng_event_field_value parent;
+
+ /*
+ * Array of `struct lttng_event_field_value *` (owned by this).
+ *
+ * A `NULL` element means it's unavailable
+ * (`LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE` status).
+ */
+ struct lttng_dynamic_pointer_array elems;
+};
+
+/*
+ * This is internal since the session daemon knows nothing about the
+ * enumeration fields produced by the kernel tracer. Indeed, the kernel tracer
+ * manages its own metadata which remains opaque to the rest of the toolchain.
+ *
+ * Enumerations could be supported for the user space tracer, but it is not the
+ * case right now.
+ */
+
+/*
+ * Sets `*count` to the number of labels of the enumeration event field
+ * value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ * * `count` is `NULL`.
+ */
+LTTNG_HIDDEN
+enum lttng_event_field_value_status
+lttng_event_field_value_enum_get_label_count(
+ const struct lttng_event_field_value *field_val,
+ unsigned int *count);
+
+/*
+ * Returns the label at index `index` of the enumeration event field
+ * value `field_val`, or `NULL` if:
+ *
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM` or
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ * * `index` is greater than or equal to the label count of `field_val`,
+ * as returned by lttng_event_field_value_enum_get_label_count().
+ */
+LTTNG_HIDDEN
+const char *lttng_event_field_value_enum_get_label_at_index(
+ const struct lttng_event_field_value *field_val,
+ unsigned int index);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_uint_create(
+ uint64_t val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_int_create(
+ int64_t val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(
+ uint64_t val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_enum_int_create(
+ int64_t val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_real_create(double val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_string_create(
+ const char *val);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(
+ const char *val, size_t size);
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_array_create(void);
+
+LTTNG_HIDDEN
+int lttng_event_field_value_enum_append_label(
+ struct lttng_event_field_value *field_val, const char *label);
+
+LTTNG_HIDDEN
+int lttng_event_field_value_enum_append_label_with_size(
+ struct lttng_event_field_value *field_val, const char *label,
+ size_t size);
+
+LTTNG_HIDDEN
+int lttng_event_field_value_array_append(
+ struct lttng_event_field_value *array_field_val,
+ struct lttng_event_field_value *field_val);
+
+LTTNG_HIDDEN
+int lttng_event_field_value_array_append_unavailable(
+ struct lttng_event_field_value *array_field_val);
+
+LTTNG_HIDDEN
+void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val);
+
+#endif /* LTTNG_EVENT_FIELD_VALUE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_EVENT_FIELD_VALUE_H
+#define LTTNG_EVENT_FIELD_VALUE_H
+
+#include <stdint.h>
+
+struct lttng_event_field_value;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Types of a event field value expression.
+ */
+enum lttng_event_field_value_type {
+ /*
+ * Unknown.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN = -2,
+
+ /*
+ * Returned by lttng_event_field_value_get_type() with an
+ * invalid parameter.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID = -1,
+
+ /*
+ * Unsigned integer event field value.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT = 0,
+
+ /*
+ * Signed integer event field value.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT = 1,
+
+ /*
+ * Unsigned enumeration event field value.
+ *
+ * This type conceptually inherits
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT`.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM = 2,
+
+ /*
+ * Signed enumeration event field value.
+ *
+ * This type conceptually inherits
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT`.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM = 3,
+
+ /*
+ * Real event field value.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_REAL = 4,
+
+ /*
+ * String event field value.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_STRING = 5,
+
+ /*
+ * Array event field value.
+ */
+ LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY = 6,
+};
+
+/*
+ * Event field value API status codes.
+ */
+enum lttng_event_field_value_status {
+ /*
+ * Event field value is not available.
+ */
+ LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE = -2,
+
+ /*
+ * Invalid parameter.
+ */
+ LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID = -1,
+
+ /*
+ * Success.
+ */
+ LTTNG_EVENT_FIELD_VALUE_STATUS_OK = 0,
+};
+
+/*
+ * Returns the type of the event field value `field_val`, or:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN`:
+ * The type of `field_val` is unknown as of this version of the
+ * LTTng control library.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID`:
+ * `field_val` is `NULL`.
+ */
+extern enum lttng_event_field_value_type lttng_event_field_value_get_type(
+ const struct lttng_event_field_value *field_val);
+
+/*
+ * Sets `*val` to the raw value of the unsigned integer/enumeration
+ * event field value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT` or
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM`.
+ * * `val` is `NULL`.
+ */
+extern enum lttng_event_field_value_status
+lttng_event_field_value_unsigned_int_get_value(
+ const struct lttng_event_field_value *field_val, uint64_t *val);
+
+/*
+ * Sets `*val` to the raw value of the signed integer/enumeration event
+ * field value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT` or
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM`.
+ * * `val` is `NULL`.
+ */
+extern enum lttng_event_field_value_status
+lttng_event_field_value_signed_int_get_value(
+ const struct lttng_event_field_value *field_val, int64_t *val);
+
+/*
+ * Sets `*val` to the raw value of the real event field value
+ * `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_REAL`.
+ * * `val` is `NULL`.
+ */
+extern enum lttng_event_field_value_status
+lttng_event_field_value_real_get_value(
+ const struct lttng_event_field_value *field_val, double *val);
+
+/*
+ * Returns the raw value (an UTF-8 C string) of the string event field
+ * value `field_val`, or `NULL` if:
+ *
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_STRING`.
+ */
+extern const char *lttng_event_field_value_string_get_value(
+ const struct lttng_event_field_value *field_val);
+
+/*
+ * Sets `*length` to the length (the number of contained elements) of
+ * the array event field value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY`.
+ * * `length` is `NULL`.
+ */
+extern enum lttng_event_field_value_status
+lttng_event_field_value_array_get_length(
+ const struct lttng_event_field_value *field_val,
+ unsigned int *length);
+
+/*
+ * Sets `*elem_field_val` to the event field value at index `index` in
+ * the array event field value `field_val`.
+ *
+ * Returns:
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_OK`:
+ * Success.
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID`:
+ * * `field_val` is `NULL`.
+ * * The type of `field_val` is not
+ * `LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY`.
+ * * `index` is greater than or equal to the length of `field_val`,
+ * as returned by lttng_event_field_value_array_get_length().
+ *
+ * `LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE`:
+ * * No event field value exists at index `index` within
+ * `field_val`.
+ */
+extern enum lttng_event_field_value_status
+lttng_event_field_value_array_get_element_at_index(
+ const struct lttng_event_field_value *field_val,
+ unsigned int index,
+ const struct lttng_event_field_value **elem_field_val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_EVENT_FIELD_VALUE_H */
--- /dev/null
+/*
+ * event-field-value.c
+ *
+ * Linux Trace Toolkit Control Library
+ *
+ * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <common/error.h>
+#include <common/macros.h>
+#include <lttng/event-field-value-internal.h>
+
+static
+struct lttng_event_field_value *create_empty_field_val(
+ enum lttng_event_field_value_type type, size_t size)
+{
+ struct lttng_event_field_value *field_val;
+
+ field_val = zmalloc(size);
+ if (!field_val) {
+ goto end;
+ }
+
+ field_val->type = type;
+
+end:
+ return field_val;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_uint_create(
+ uint64_t val)
+{
+ struct lttng_event_field_value_uint *field_val;
+
+ field_val = container_of(create_empty_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_uint, parent);
+ if (!field_val) {
+ goto error;
+ }
+
+ field_val->val = val;
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return &field_val->parent;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_int_create(
+ int64_t val)
+{
+ struct lttng_event_field_value_int *field_val;
+
+ field_val = container_of(create_empty_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_int, parent);
+ if (!field_val) {
+ goto error;
+ }
+
+ field_val->val = val;
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return &field_val->parent;
+}
+
+static
+struct lttng_event_field_value_enum *create_enum_field_val(
+ enum lttng_event_field_value_type type, size_t size)
+{
+ struct lttng_event_field_value_enum *field_val;
+
+ field_val = container_of(create_empty_field_val(type, size),
+ struct lttng_event_field_value_enum, parent);
+ if (!field_val) {
+ goto error;
+ }
+
+ lttng_dynamic_pointer_array_init(&field_val->labels, free);
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return field_val;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(
+ uint64_t val)
+{
+ struct lttng_event_field_value_enum_uint *field_val;
+
+ field_val = container_of(create_enum_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_enum_uint, parent);
+ if (!field_val) {
+ goto error;
+ }
+
+ field_val->val = val;
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent.parent);
+
+end:
+ return &field_val->parent.parent;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_enum_int_create(
+ int64_t val)
+{
+ struct lttng_event_field_value_enum_int *field_val;
+
+ field_val = container_of(create_enum_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_enum_int, parent);
+ if (!field_val) {
+ goto error;
+ }
+
+ field_val->val = val;
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent.parent);
+
+end:
+ return &field_val->parent.parent;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_real_create(double val)
+{
+ struct lttng_event_field_value_real *field_val = container_of(
+ create_empty_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_REAL,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_real, parent);
+
+ if (!field_val) {
+ goto error;
+ }
+
+ field_val->val = val;
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return &field_val->parent;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(
+ const char *val, size_t size)
+{
+ struct lttng_event_field_value_string *field_val = container_of(
+ create_empty_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_STRING,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_string, parent);
+
+ if (!field_val) {
+ goto error;
+ }
+
+ assert(val);
+ field_val->val = strndup(val, size);
+ if (!field_val->val) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return &field_val->parent;
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_string_create(
+ const char *val)
+{
+ assert(val);
+ return lttng_event_field_value_string_create_with_size(val,
+ strlen(val));
+}
+
+static
+void destroy_field_val(void *field_val)
+{
+ lttng_event_field_value_destroy(field_val);
+}
+
+LTTNG_HIDDEN
+struct lttng_event_field_value *lttng_event_field_value_array_create(void)
+{
+ struct lttng_event_field_value_array *field_val = container_of(
+ create_empty_field_val(
+ LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY,
+ sizeof(*field_val)),
+ struct lttng_event_field_value_array, parent);
+
+ if (!field_val) {
+ goto error;
+ }
+
+ lttng_dynamic_pointer_array_init(&field_val->elems, destroy_field_val);
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(&field_val->parent);
+
+end:
+ return &field_val->parent;
+}
+
+LTTNG_HIDDEN
+void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val)
+{
+ if (!field_val) {
+ goto end;
+ }
+
+ switch (field_val->type) {
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
+ {
+ struct lttng_event_field_value_enum *enum_field_val =
+ container_of(field_val,
+ struct lttng_event_field_value_enum, parent);
+
+ lttng_dynamic_pointer_array_reset(&enum_field_val->labels);
+ break;
+ }
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
+ {
+ struct lttng_event_field_value_string *str_field_val =
+ container_of(field_val,
+ struct lttng_event_field_value_string, parent);
+
+ free(str_field_val->val);
+ break;
+ }
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
+ {
+ struct lttng_event_field_value_array *array_field_expr =
+ container_of(field_val,
+ struct lttng_event_field_value_array,
+ parent);
+
+ lttng_dynamic_pointer_array_reset(&array_field_expr->elems);
+ break;
+ }
+ default:
+ break;
+ }
+
+ free(field_val);
+
+end:
+ return;
+}
+
+LTTNG_HIDDEN
+int lttng_event_field_value_enum_append_label_with_size(
+ struct lttng_event_field_value *field_val,
+ const char *label, size_t size)
+{
+ int ret;
+ char *new_label;
+
+ assert(field_val);
+ assert(label);
+ new_label = strndup(label, size);
+ if (!new_label) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = lttng_dynamic_pointer_array_add_pointer(
+ &container_of(field_val,
+ struct lttng_event_field_value_enum, parent)->labels,
+ new_label);
+ if (ret == 0) {
+ new_label = NULL;
+ }
+
+end:
+ free(new_label);
+ return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_event_field_value_enum_append_label(
+ struct lttng_event_field_value *field_val,
+ const char *label)
+{
+ assert(label);
+ return lttng_event_field_value_enum_append_label_with_size(field_val,
+ label, strlen(label));
+}
+
+LTTNG_HIDDEN
+int lttng_event_field_value_array_append(
+ struct lttng_event_field_value *array_field_val,
+ struct lttng_event_field_value *field_val)
+{
+ assert(array_field_val);
+ assert(field_val);
+ return lttng_dynamic_pointer_array_add_pointer(
+ &container_of(array_field_val,
+ struct lttng_event_field_value_array, parent)->elems,
+ field_val);
+}
+
+LTTNG_HIDDEN
+int lttng_event_field_value_array_append_unavailable(
+ struct lttng_event_field_value *array_field_val)
+{
+ assert(array_field_val);
+ return lttng_dynamic_pointer_array_add_pointer(
+ &container_of(array_field_val,
+ struct lttng_event_field_value_array, parent)->elems,
+ NULL);
+}
+
+enum lttng_event_field_value_type lttng_event_field_value_get_type(
+ const struct lttng_event_field_value *field_val)
+{
+ enum lttng_event_field_value_type type;
+
+ if (!field_val) {
+ type = LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID;
+ goto end;
+ }
+
+ type = field_val->type;
+
+end:
+ return type;
+}
+
+enum lttng_event_field_value_status
+lttng_event_field_value_unsigned_int_get_value(
+ const struct lttng_event_field_value *field_val, uint64_t *val)
+{
+ enum lttng_event_field_value_status status;
+
+ if (!field_val || !val) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ switch (field_val->type) {
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
+ *val = container_of(field_val,
+ const struct lttng_event_field_value_uint,
+ parent)->val;
+ break;
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
+ *val = container_of(
+ container_of(field_val,
+ const struct lttng_event_field_value_enum,
+ parent),
+ const struct lttng_event_field_value_enum_uint,
+ parent)->val;
+ break;
+ default:
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+
+end:
+ return status;
+}
+
+enum lttng_event_field_value_status
+lttng_event_field_value_signed_int_get_value(
+ const struct lttng_event_field_value *field_val, int64_t *val)
+{
+ enum lttng_event_field_value_status status;
+
+ if (!field_val || !val) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ switch (field_val->type) {
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
+ *val = container_of(field_val,
+ const struct lttng_event_field_value_int,
+ parent)->val;
+ break;
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
+ *val = container_of(
+ container_of(field_val,
+ const struct lttng_event_field_value_enum,
+ parent),
+ const struct lttng_event_field_value_enum_int,
+ parent)->val;
+ break;
+ default:
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+
+end:
+ return status;
+}
+
+enum lttng_event_field_value_status
+lttng_event_field_value_real_get_value(
+ const struct lttng_event_field_value *field_val, double *val)
+{
+ enum lttng_event_field_value_status status;
+
+ if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_REAL ||
+ !val) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ *val = container_of(field_val,
+ const struct lttng_event_field_value_real, parent)->val;
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+
+end:
+ return status;
+}
+
+static
+bool is_enum_field_val(const struct lttng_event_field_value *field_val)
+{
+ return field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM ||
+ field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM;
+}
+
+enum lttng_event_field_value_status
+lttng_event_field_value_enum_get_label_count(
+ const struct lttng_event_field_value *field_val,
+ unsigned int *count)
+{
+ enum lttng_event_field_value_status status;
+
+ if (!field_val || !is_enum_field_val(field_val) || !count) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ *count = (unsigned int) lttng_dynamic_pointer_array_get_count(
+ &container_of(field_val,
+ const struct lttng_event_field_value_enum,
+ parent)->labels);
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+
+end:
+ return status;
+}
+
+const char *lttng_event_field_value_enum_get_label_at_index(
+ const struct lttng_event_field_value *field_val,
+ unsigned int index)
+{
+ const char *ret;
+ const struct lttng_event_field_value_enum *enum_field_val;
+
+ if (!field_val || !is_enum_field_val(field_val)) {
+ ret = NULL;
+ goto end;
+ }
+
+ enum_field_val = container_of(field_val,
+ const struct lttng_event_field_value_enum, parent);
+
+ if (index >= lttng_dynamic_pointer_array_get_count(&enum_field_val->labels)) {
+ ret = NULL;
+ goto end;
+ }
+
+ ret = lttng_dynamic_pointer_array_get_pointer(&enum_field_val->labels,
+ index);
+
+end:
+ return ret;
+}
+
+const char *lttng_event_field_value_string_get_value(
+ const struct lttng_event_field_value *field_val)
+{
+ const char *ret;
+
+ if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_STRING) {
+ ret = NULL;
+ goto end;
+ }
+
+ ret = container_of(field_val,
+ const struct lttng_event_field_value_string, parent)->val;
+
+end:
+ return ret;
+}
+
+enum lttng_event_field_value_status lttng_event_field_value_array_get_length(
+ const struct lttng_event_field_value *field_val,
+ unsigned int *length)
+{
+ enum lttng_event_field_value_status status;
+
+ if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
+ !length) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ *length = (unsigned int) lttng_dynamic_pointer_array_get_count(
+ &container_of(field_val,
+ const struct lttng_event_field_value_array,
+ parent)->elems);
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+
+end:
+ return status;
+}
+
+enum lttng_event_field_value_status
+lttng_event_field_value_array_get_element_at_index(
+ const struct lttng_event_field_value *field_val,
+ unsigned int index,
+ const struct lttng_event_field_value **elem_field_val)
+{
+ enum lttng_event_field_value_status status;
+ const struct lttng_event_field_value_array *array_field_val;
+
+ if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
+ !elem_field_val) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ array_field_val = container_of(field_val,
+ const struct lttng_event_field_value_array, parent);
+
+ if (index >= lttng_dynamic_pointer_array_get_count(&array_field_val->elems)) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
+ goto end;
+ }
+
+ *elem_field_val = lttng_dynamic_pointer_array_get_pointer(
+ &array_field_val->elems, index);
+ if (*elem_field_val) {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
+ } else {
+ status = LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE;
+ }
+
+end:
+ return status;
+}