+static
+int event_field_value_from_obj(const msgpack_object *obj,
+ struct lttng_event_field_value **field_val)
+{
+ int ret = 0;
+
+ assert(obj);
+ assert(field_val);
+
+ switch (obj->type) {
+ case MSGPACK_OBJECT_NIL:
+ /* Unavailable. */
+ *field_val = NULL;
+ goto end;
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ *field_val = lttng_event_field_value_uint_create(
+ obj->via.u64);
+ break;
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ *field_val = lttng_event_field_value_int_create(
+ obj->via.i64);
+ break;
+ case MSGPACK_OBJECT_FLOAT32:
+ case MSGPACK_OBJECT_FLOAT64:
+ *field_val = lttng_event_field_value_real_create(
+ obj->via.f64);
+ break;
+ case MSGPACK_OBJECT_STR:
+ *field_val = lttng_event_field_value_string_create_with_size(
+ obj->via.str.ptr, obj->via.str.size);
+ break;
+ case MSGPACK_OBJECT_ARRAY:
+ {
+ size_t i;
+
+ *field_val = lttng_event_field_value_array_create();
+ if (!*field_val) {
+ goto error;
+ }
+
+ for (i = 0; i < obj->via.array.size; i++) {
+ const msgpack_object *elem_obj = &obj->via.array.ptr[i];
+ struct lttng_event_field_value *elem_field_val;
+
+ ret = event_field_value_from_obj(elem_obj,
+ &elem_field_val);
+ if (ret) {
+ goto error;
+ }
+
+ if (elem_field_val) {
+ ret = lttng_event_field_value_array_append(
+ *field_val, elem_field_val);
+ } else {
+ ret = lttng_event_field_value_array_append_unavailable(
+ *field_val);
+ }
+
+ if (ret) {
+ lttng_event_field_value_destroy(elem_field_val);
+ goto error;
+ }
+ }
+
+ break;
+ }
+ case MSGPACK_OBJECT_MAP:
+ {
+ /*
+ * As of this version, the only valid map object is
+ * for an enumeration value, for example:
+ *
+ * type: enum
+ * value: 177
+ * labels:
+ * - Labatt 50
+ * - Molson Dry
+ * - Carling Black Label
+ */
+ const msgpack_object *inner_obj;
+ size_t label_i;
+
+ inner_obj = get_msgpack_map_obj(obj, "type");
+ if (!inner_obj) {
+ ERR("Missing `type` entry in map object");
+ goto error;
+ }
+
+ if (inner_obj->type != MSGPACK_OBJECT_STR) {
+ ERR("Map object's `type` entry is not a string: type = %s",
+ msgpack_object_type_str(inner_obj->type));
+ goto error;
+ }
+
+ if (!msgpack_str_is_equal(inner_obj, "enum")) {
+ ERR("Map object's `type` entry: expecting `enum`");
+ goto error;
+ }
+
+ inner_obj = get_msgpack_map_obj(obj, "value");
+ if (!inner_obj) {
+ ERR("Missing `value` entry in map object");
+ goto error;
+ }
+
+ if (inner_obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER) {
+ *field_val = lttng_event_field_value_enum_uint_create(
+ inner_obj->via.u64);
+ } else if (inner_obj->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
+ *field_val = lttng_event_field_value_enum_int_create(
+ inner_obj->via.i64);
+ } else {
+ ERR("Map object's `value` entry is not an integer: type = %s",
+ msgpack_object_type_str(inner_obj->type));
+ goto error;
+ }
+
+ if (!*field_val) {
+ goto error;
+ }
+
+ inner_obj = get_msgpack_map_obj(obj, "labels");
+ if (!inner_obj) {
+ /* No labels */
+ goto end;
+ }
+
+ if (inner_obj->type != MSGPACK_OBJECT_ARRAY) {
+ ERR("Map object's `labels` entry is not an array: type = %s",
+ msgpack_object_type_str(inner_obj->type));
+ goto error;
+ }
+
+ for (label_i = 0; label_i < inner_obj->via.array.size;
+ label_i++) {
+ int iret;
+ const msgpack_object *elem_obj =
+ &inner_obj->via.array.ptr[label_i];
+
+ if (elem_obj->type != MSGPACK_OBJECT_STR) {
+ ERR("Map object's `labels` entry's type is not a string: type = %s",
+ msgpack_object_type_str(elem_obj->type));
+ goto error;
+ }
+
+ iret = lttng_event_field_value_enum_append_label_with_size(
+ *field_val, elem_obj->via.str.ptr,
+ elem_obj->via.str.size);
+ if (iret) {
+ goto error;
+ }
+ }
+
+ break;
+ }
+ default:
+ ERR("Unexpected object type: type = %s",
+ msgpack_object_type_str(obj->type));
+ goto error;
+ }
+
+ if (!*field_val) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(*field_val);
+ *field_val = NULL;
+ ret = -1;
+
+end:
+ return ret;
+}
+
+static
+struct lttng_event_field_value *event_field_value_from_capture_payload(
+ const struct lttng_condition_event_rule *condition,
+ const char *capture_payload, size_t capture_payload_size)
+{
+ struct lttng_event_field_value *ret = NULL;
+ msgpack_unpacked unpacked;
+ msgpack_unpack_return unpack_return;
+ const msgpack_object *root_obj;
+ const msgpack_object_array *root_array_obj;
+ size_t i;
+ size_t count;
+
+ assert(condition);
+ assert(capture_payload);
+
+ /* Initialize value. */
+ msgpack_unpacked_init(&unpacked);
+
+ /* Decode. */
+ unpack_return = msgpack_unpack_next(&unpacked, capture_payload,
+ capture_payload_size, NULL);
+ if (unpack_return != MSGPACK_UNPACK_SUCCESS) {
+ ERR("msgpack_unpack_next() failed to decode the "
+ "MessagePack-encoded capture payload: "
+ "size = %zu, ret = %d",
+ capture_payload_size, unpack_return);
+ goto error;
+ }
+
+ /* Get root array. */
+ root_obj = &unpacked.data;
+
+ if (root_obj->type != MSGPACK_OBJECT_ARRAY) {
+ ERR("Expecting an array as the root object: type = %s",
+ msgpack_object_type_str(root_obj->type));
+ goto error;
+ }
+
+ root_array_obj = &root_obj->via.array;
+
+ /* Create an empty root array event field value. */
+ ret = lttng_event_field_value_array_create();
+ if (!ret) {
+ goto error;
+ }
+
+ /*
+ * For each capture descriptor in the condition object:
+ *
+ * 1. Get its corresponding captured field value MessagePack
+ * object.
+ *
+ * 2. Create a corresponding event field value.
+ *
+ * 3. Append it to `ret` (the root array event field value).
+ */
+ count = lttng_dynamic_pointer_array_get_count(
+ &condition->capture_descriptors);
+ assert(count > 0);
+
+ for (i = 0; i < count; i++) {
+ const struct lttng_capture_descriptor *capture_descriptor =
+ lttng_condition_event_rule_get_internal_capture_descriptor_at_index(
+ &condition->parent, i);
+ const msgpack_object *elem_obj;
+ struct lttng_event_field_value *elem_field_val;
+ int iret;
+
+ assert(capture_descriptor);
+
+ elem_obj = &root_array_obj->ptr[i];
+ iret = event_field_value_from_obj(elem_obj,
+ &elem_field_val);
+ if (iret) {
+ goto error;
+ }
+
+ if (elem_field_val) {
+ iret = lttng_event_field_value_array_append(ret,
+ elem_field_val);
+ } else {
+ iret = lttng_event_field_value_array_append_unavailable(
+ ret);
+ }
+
+ if (iret) {
+ lttng_event_field_value_destroy(elem_field_val);
+ goto error;
+ }
+ }
+
+ goto end;
+
+error:
+ lttng_event_field_value_destroy(ret);
+ ret = NULL;
+
+end:
+ msgpack_unpacked_destroy(&unpacked);
+ return ret;
+}
+