From be83bc717db0375e19431fe38c0490ff1a9e40ec Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 26 Apr 2017 05:57:37 -0700 Subject: 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 ) and buf. --- buf.c | 24 ++++++++++++++++++++++++ buf.h | 3 +++ ffi.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) 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); -- cgit v1.2.3