summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-04 23:22:08 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-04 23:22:08 -0700
commitf7b1729c070b1264fbe0c05d9e734d0c565bf64e (patch)
tree22f4258bb80b5d1cc950d5c405eb0c694b86eec8
parent0855c5c330332eee1adb61c9fb9c9e69636c2051 (diff)
downloadtxr-f7b1729c070b1264fbe0c05d9e734d0c565bf64e.tar.gz
txr-f7b1729c070b1264fbe0c05d9e734d0c565bf64e.tar.bz2
txr-f7b1729c070b1264fbe0c05d9e734d0c565bf64e.zip
ffi: functions for type-system-driven buffer coding.
* ffi.c (ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out): New functions. (ffi_init): ffi-put-into, ffi-put, ffi-in, ffi-get, ffi-out: intrinsics registered. * ffi.h (ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out): Declared.
-rw-r--r--ffi.c61
-rw-r--r--ffi.h5
2 files changed, 66 insertions, 0 deletions
diff --git a/ffi.c b/ffi.c
index a079ceaf..ffeb3987 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1849,6 +1849,62 @@ val ffi_typedef(val name, val type)
return sethash(ffi_typedef_hash, name, type);
}
+val ffi_put_into(val dstbuf, val obj, val type)
+{
+ val self = lit("ffi-put-into");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ mem_t *dst = buf_get(dstbuf, self);
+ if (lt(length_buf(dstbuf), num_fast(tft->size)))
+ uw_throwf(lit("~a: buffer ~s is too small for type ~s"),
+ self, dstbuf, type, nao);
+ tft->put(tft, obj, dst, self);
+ return dstbuf;
+}
+
+val ffi_put(val obj, val type)
+{
+ val self = lit("ffi-put");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ val buf = make_buf(num_fast(tft->size), zero, nil);
+ mem_t *dst = buf_get(buf, self);
+ tft->put(tft, obj, dst, self);
+ return buf;
+}
+
+val ffi_in(val srcbuf, val obj, val type)
+{
+ val self = lit("ffi-in");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ mem_t *src = buf_get(srcbuf, self);
+ if (lt(length_buf(srcbuf), num_fast(tft->size)))
+ uw_throwf(lit("~a: buffer ~s is too small for type ~s"),
+ self, srcbuf, type, nao);
+ return tft->in(tft, src, obj, self);
+}
+
+val ffi_get(val srcbuf, val type)
+{
+ val self = lit("ffi-get");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ mem_t *src = buf_get(srcbuf, self);
+ if (lt(length_buf(srcbuf), num_fast(tft->size)))
+ uw_throwf(lit("~a: buffer ~s is too small for type ~s"),
+ self, srcbuf, type, nao);
+ return tft->get(tft, src, self);
+}
+
+val ffi_out(val dstbuf, val obj, val type, val copy_p)
+{
+ val self = lit("ffi-out");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ mem_t *dst = buf_get(dstbuf, self);
+ if (lt(length_buf(dstbuf), num_fast(tft->size)))
+ uw_throwf(lit("~a: buffer ~s is too small for type ~s"),
+ self, dstbuf, type, nao);
+ tft->out(tft, copy_p != nil, obj, dst, self);
+ return dstbuf;
+}
+
void ffi_init(void)
{
prot1(&ffi_typedef_hash);
@@ -1898,6 +1954,11 @@ void ffi_init(void)
reg_fun(intern(lit("ffi-make-closure"), user_package), func_n2(ffi_make_closure));
reg_fun(intern(lit("cptr"), user_package), func_n1o(cptr_make, 0));
reg_fun(intern(lit("ffi-typedef"), user_package), func_n2(ffi_typedef));
+ reg_fun(intern(lit("ffi-put-into"), user_package), func_n3(ffi_put_into));
+ reg_fun(intern(lit("ffi-put"), user_package), func_n2(ffi_put));
+ reg_fun(intern(lit("ffi-in"), user_package), func_n3(ffi_in));
+ reg_fun(intern(lit("ffi-get"), user_package), func_n2(ffi_get));
+ reg_fun(intern(lit("ffi-out"), user_package), func_n4(ffi_out));
reg_varl(intern(lit("cptr-null"), user_package), cptr(0));
ffi_typedef_hash = make_hash(nil, nil, nil);
ffi_init_types();
diff --git a/ffi.h b/ffi.h
index c598044f..bd8b61fb 100644
--- a/ffi.h
+++ b/ffi.h
@@ -57,4 +57,9 @@ val ffi_make_closure(val fun, val call_desc);
mem_t *ffi_closure_get_fptr(val closure);
val ffi_call_wrap(val ffi_call_desc, val fptr, val args);
val ffi_typedef(val name, val type);
+val ffi_put_into(val dstbuf, val obj, val type);
+val ffi_put(val obj, val type);
+val ffi_in(val srcbuf, val obj, val type);
+val ffi_get(val srcbuf, val type);
+val ffi_out(val dstbuf, val obj, val type, val copy_p);
void ffi_init(void);