summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-04-26 05:57:37 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-04-26 05:57:37 -0700
commitbe83bc717db0375e19431fe38c0490ff1a9e40ec (patch)
tree354d2107e8a5d4b518b5081a036894b87fc82c68
parentd081a595dfa053c78f7e3f580f82ca7823f02f74 (diff)
downloadtxr-be83bc717db0375e19431fe38c0490ff1a9e40ec.tar.gz
txr-be83bc717db0375e19431fe38c0490ff1a9e40ec.tar.bz2
txr-be83bc717db0375e19431fe38c0490ff1a9e40ec.zip
ffi: support buf objects.
* buf.c (make_duplicate_buf, buf_get, buf_fill): New functions. * buf.h (make_duplicate_buf, buf_get, buf_fill): Declared. * ffi.c (struct txr_ffi_type): New member, nelem. Keeps track of number of elements, for types that are FFI pointers. This lets us support the get method so that a buf can be a C function return value, if its size is declared in our FFI type system. (ffi_buf_put, ffi_buf_get, ffi_buf_fill): New functions. (ffi_type_compile): Handle two new cases of syntax for buffers: (buf <size>) and buf.
-rw-r--r--buf.c24
-rw-r--r--buf.h3
-rw-r--r--ffi.c39
3 files changed, 66 insertions, 0 deletions
diff --git a/buf.c b/buf.c
index 0c1ecf18..58cd4177 100644
--- a/buf.c
+++ b/buf.c
@@ -107,6 +107,18 @@ val make_borrowed_buf(val len, mem_t *data)
return obj;
}
+val make_duplicate_buf(val len, mem_t *data)
+{
+ val obj = make_obj();
+
+ obj->b.type = BUF;
+ obj->b.data = chk_copy_obj(data, c_num(len));
+ obj->b.len = len;
+ obj->b.size = nil;
+
+ return obj;
+}
+
static struct buf *buf_handle(val buf, val ctx)
{
if (type(buf) == BUF)
@@ -186,6 +198,18 @@ val length_buf(val buf)
return b->len;
}
+mem_t *buf_get(val buf, val self)
+{
+ struct buf *b = buf_handle(buf, self);
+ return b->data;
+}
+
+void buf_fill(val buf, mem_t *src, val self)
+{
+ struct buf *b = buf_handle(buf, self);
+ memcpy(b->data, src, c_num(b->len));
+}
+
static void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
{
struct buf *b = buf_handle(buf, self);
diff --git a/buf.h b/buf.h
index 56a04c7e..8102fff8 100644
--- a/buf.h
+++ b/buf.h
@@ -27,9 +27,12 @@
val make_buf(val len, val init_val, val alloc_size);
val make_borrowed_buf(val len, mem_t *data);
+val make_duplicate_buf(val len, mem_t *data);
val buf_trim(val buf);
val buf_set_length(val obj, val len, val init_val);
val length_buf(val buf);
+mem_t *buf_get(val buf, val self);
+void buf_fill(val buf, mem_t *src, val self);
#if HAVE_I8
val buf_put_i8(val buf, val pos, val num);
diff --git a/ffi.c b/ffi.c
index 4c5c5399..00143b87 100644
--- a/ffi.c
+++ b/ffi.c
@@ -83,6 +83,7 @@ struct txr_ffi_type {
val mnames;
val mtypes;
cnum size, align;
+ cnum nelem;
void (*put)(struct txr_ffi_type *, val obj, mem_t *dst, val self);
val (*get)(struct txr_ffi_type *, mem_t *src, val self);
void (*fill)(struct txr_ffi_type *, mem_t *src, val obj, val self);
@@ -587,6 +588,28 @@ static val ffi_wstr_get(struct txr_ffi_type *tft, mem_t *src, val self)
return string(p);
}
+static void ffi_buf_put(struct txr_ffi_type *tft,
+ val buf, mem_t *dst, val self)
+{
+ mem_t *b = buf_get(buf, self);
+ *coerce(const mem_t **, dst) = b;
+}
+
+static val ffi_buf_get(struct txr_ffi_type *tft, mem_t *src, val self)
+{
+ (void) tft;
+ (void) self;
+ mem_t *p = *coerce(mem_t **, src);
+ return make_duplicate_buf(num(tft->nelem), p);
+}
+
+static void ffi_buf_fill(struct txr_ffi_type *tft, mem_t *src,
+ val buf, val self)
+{
+ (void) tft;
+ buf_fill(buf, src, self);
+}
+
static void ffi_ptr_in_put(struct txr_ffi_type *tft,
val s, mem_t *dst, val self)
{
@@ -866,6 +889,15 @@ val ffi_type_compile(val syntax)
&ffi_type_pointer,
ffi_ptr_in_out_put, ffi_ptr_out_get,
target_type);
+ } else if (sym == buf_s) {
+ cnum nelem = c_num(cadr(syntax));
+ val type = make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
+ &ffi_type_pointer,
+ ffi_buf_put, ffi_buf_get);
+ struct txr_ffi_type *tft = ffi_type_struct(type);
+ tft->fill = ffi_buf_fill;
+ tft->nelem = nelem;
+ return type;
}
uw_throwf(error_s, lit("~a: unimplemented case"), self, nao);
@@ -965,6 +997,13 @@ val ffi_type_compile(val syntax)
return make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,
ffi_wstr_put, ffi_wstr_get);
+ } else if (syntax == buf_s) {
+ val type = make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
+ &ffi_type_pointer,
+ ffi_buf_put, ffi_void_get);
+ struct txr_ffi_type *tft = ffi_type_struct(type);
+ tft->fill = ffi_buf_fill;
+ return type;
} else if (syntax == void_s) {
return make_ffi_type_builtin(syntax, nil, 0, &ffi_type_void,
ffi_void_put, ffi_void_get);