+/*
+ * Serializes the C string `str` into `buf`.
+ *
+ * Encoding is the length of `str` plus one (for the null character),
+ * and then the string, including its null terminator.
+ */
+static
+int serialize_cstr(const char *str, struct lttng_dynamic_buffer *buf)
+{
+ int ret;
+ const uint32_t len = strlen(str) + 1;
+
+ /* Serialize the length, including the null terminator. */
+ DBG("Serializing C string's length (including null terminator): "
+ "%" PRIu32, len);
+ ret = lttng_dynamic_buffer_append(buf, &len, sizeof(len));
+ if (ret) {
+ goto end;
+ }
+
+ /* Serialize the string. */
+ DBG("Serializing C string: '%s'", str);
+ ret = lttng_dynamic_buffer_append(buf, str, len);
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Serializes the event expression `expr` into `buf`.
+ */
+static
+int serialize_event_expr(const struct lttng_event_expr *expr,
+ struct lttng_payload *payload)
+{
+ const uint8_t type = expr->type;
+ int ret;
+
+ /* Serialize the expression's type. */
+ DBG("Serializing event expression's type: %d", expr->type);
+ ret = lttng_dynamic_buffer_append(&payload->buffer, &type, sizeof(type));
+ if (ret) {
+ goto end;
+ }
+
+ /* Serialize the expression */
+ switch (expr->type) {
+ case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
+ case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
+ {
+ const struct lttng_event_expr_field *field_expr =
+ container_of(expr,
+ const struct lttng_event_expr_field,
+ parent);
+
+ /* Serialize the field name. */
+ DBG("Serializing field event expression's field name: '%s'",
+ field_expr->name);
+ ret = serialize_cstr(field_expr->name, &payload->buffer);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
+ {
+ const struct lttng_event_expr_app_specific_context_field *field_expr =
+ container_of(expr,
+ const struct lttng_event_expr_app_specific_context_field,
+ parent);
+
+ /* Serialize the provider name. */
+ DBG("Serializing app-specific context field event expression's "
+ "provider name: '%s'",
+ field_expr->provider_name);
+ ret = serialize_cstr(field_expr->provider_name, &payload->buffer);
+ if (ret) {
+ goto end;
+ }
+
+ /* Serialize the type name. */
+ DBG("Serializing app-specific context field event expression's "
+ "type name: '%s'",
+ field_expr->provider_name);
+ ret = serialize_cstr(field_expr->type_name, &payload->buffer);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
+ {
+ const struct lttng_event_expr_array_field_element *elem_expr =
+ container_of(expr,
+ const struct lttng_event_expr_array_field_element,
+ parent);
+ const uint32_t index = elem_expr->index;
+
+ /* Serialize the index. */
+ DBG("Serializing array field element event expression's "
+ "index: %u", elem_expr->index);
+ ret = lttng_dynamic_buffer_append(&payload->buffer, &index, sizeof(index));
+ if (ret) {
+ goto end;
+ }
+
+ /* Serialize the parent array field expression. */
+ DBG("Serializing array field element event expression's "
+ "parent array field event expression.");
+ ret = serialize_event_expr(elem_expr->array_field_expr, payload);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+