aboutgitcodelistschat:MatrixIRC
path: root/cooker/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'cooker/call.c')
-rw-r--r--cooker/call.c61
1 files changed, 55 insertions, 6 deletions
diff --git a/cooker/call.c b/cooker/call.c
index bb53829..dd37fe9 100644
--- a/cooker/call.c
+++ b/cooker/call.c
@@ -72,7 +72,7 @@ static union value parse_metadata(struct gluten_ctx *g, struct field *f,
if (tag_offset.type == OFFSET_NULL)
die(" tag not found");
- if ((*base_offset)->type == OFFSET_NULL) {
+ if ((*base_offset)->type == OFFSET_NULL || (f->flags & WBUF)) {
**base_offset = tag_offset;
} else if (f->flags & MASK || add) {
emit_bitwise(g, f->type, BITWISE_OR, offset, offset,
@@ -133,6 +133,10 @@ Examples of arguments:
- STRING: abcd write abcd to ro_data (using size), and pointer to it
parse_arg() passes ro_data offset
+- IOV: <tag> write (one!) struct iovec with iov_base pointer to tag
+ parse_arg() passes null offset
+ parse_field() gives back data offset
+
- STRUCT: 1, 2 write struct to ro_data, and pointer to it
parse_arg() passes ro_data offset
@@ -169,12 +173,38 @@ static union value parse_field(struct gluten_ctx *g, struct arg *args,
(tmp1 = json_value_get_object(jvalue)) && is_metadata_obj(tmp1)) {
v = parse_metadata(g, f, &base_offset, offset, tmp1, dry_run,
add);
- if (v.v_num == 0)
+ if (!(f->flags & IOV) && v.v_num == 0)
+ return v;
+ }
+
+ if (f->flags & IOV) {
+ struct gluten_offset iov;
+ struct iovec *iovp;
+ intptr_t *msg_iov;
+
+ if (dry_run)
return v;
+
+ /* iov_base: v */
+ /* iov_len: at the moment from field */
+ msg_iov = (intptr_t *)gluten_ptr(&g->g, offset);
+
+ iov = gluten_rw_alloc(g, sizeof(struct iovec));
+ iovp = (struct iovec *)gluten_ptr(&g->g, iov);
+ iovp->iov_base = (void *)(intptr_t)base_offset->offset;
+ gluten_relocation_add(g, iov);
+
+ iovp->iov_len = f->size;
+
+ *msg_iov = iov.offset;
+ gluten_relocation_add(g, offset);
+
+ return v;
}
if (!jvalue && !(f->flags & SIZE))
return v;
+
switch (f->type) {
case USHORT:
case INT:
@@ -249,12 +279,28 @@ static union value parse_field(struct gluten_ctx *g, struct arg *args,
tmp1 = json_value_get_object(jvalue);
f_value = json_object_get_value(tmp1, f_inner->name);
- debug(" parse struct internal value:%s",
+ debug(" parse struct, field %s, internal value:%s",
+ f_inner->name,
json_serialize_to_string(f_value));
- if (!f_value)
+ if (!f_value && !(f_inner->flags & SIZE))
continue;
- parse_field(g, args, &struct_start, index, f_inner,
- f_value, false, add);
+
+ if (f_inner->size && f_inner->type == SELECT) {
+ struct gluten_offset ptr_offset;
+ intptr_t *link;
+
+ ptr_offset = gluten_rw_alloc(g, f_inner->size);
+ parse_field(g, args, &ptr_offset, index, f_inner,
+ f_value, false, add);
+
+ link = (intptr_t *)gluten_ptr(&g->g, offset);
+ *link = ptr_offset.offset;
+ gluten_relocation_add(g, offset);
+ } else {
+ parse_field(g, args, &struct_start, index, f_inner,
+ f_value, false, add);
+ }
+
if (base_offset->type == OFFSET_NULL)
*base_offset = struct_start;
}
@@ -278,6 +324,9 @@ bool arg_needs_temp(struct field *f, int pos, JSON_Value *jvalue,
if (f->flags & COPY_ON_CALL)
return true;
+ if (f->flags & IOV)
+ return true;
+
if (f->flags & SIZE)
return false;