summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c76
-rw-r--r--ffi.h8
-rw-r--r--txr.122
3 files changed, 72 insertions, 34 deletions
diff --git a/ffi.c b/ffi.c
index f06d524f..625545bb 100644
--- a/ffi.c
+++ b/ffi.c
@@ -4475,15 +4475,21 @@ val ffi_elemtype(val type)
return eltype;
}
-val ffi_put_into(val dstbuf, val obj, val type)
+val ffi_put_into(val dstbuf, val obj, val type, val offset_in)
{
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(error_s, lit("~a: buffer ~s is too small for type ~s"),
- self, dstbuf, type, nao);
- tft->put(tft, obj, dst, self);
+ val offset = default_arg(offset_in, zero);
+ cnum offsn = c_num(offset);
+ cnum room = c_num(minus(length_buf(dstbuf), offset));
+ if (offsn < 0)
+ uw_throwf(error_s, lit("~a: negative offset ~s specified"),
+ self, offset, nao);
+ if (room < tft->size)
+ uw_throwf(error_s, lit("~a: buffer ~s is too small for type ~s at offset ~s"),
+ self, dstbuf, type, offset, nao);
+ tft->put(tft, obj, dst + offsn, self);
return dstbuf;
}
@@ -4497,44 +4503,62 @@ val ffi_put(val obj, val type)
return buf;
}
-val ffi_in(val srcbuf, val obj, val type, val copy_p)
+val ffi_in(val srcbuf, val obj, val type, val copy_p, val offset_in)
{
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(error_s, lit("~a: buffer ~s is too small for type ~s"),
- self, srcbuf, type, nao);
+ val offset = default_arg(offset_in, zero);
+ cnum offsn = c_num(offset);
+ cnum room = c_num(minus(length_buf(srcbuf), offset));
+ if (offsn < 0)
+ uw_throwf(error_s, lit("~a: negative offset ~s specified"),
+ self, offset, nao);
+ if (room < tft->size)
+ uw_throwf(error_s, lit("~a: buffer ~s is too small for type ~s at offset ~s"),
+ self, srcbuf, type, offset, nao);
if (tft->in != 0)
- return tft->in(tft, copy_p != nil, src, obj, self);
+ return tft->in(tft, copy_p != nil, src + offsn, obj, self);
else if (copy_p)
- return tft->get(tft, src, self);
+ return tft->get(tft, src + offsn, self);
return obj;
}
-val ffi_get(val srcbuf, val type)
+val ffi_get(val srcbuf, val type, val offset_in)
{
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(error_s, lit("~a: buffer ~s is too small for type ~s"),
- self, srcbuf, type, nao);
- return tft->get(tft, src, self);
+ val offset = default_arg(offset_in, zero);
+ cnum offsn = c_num(offset);
+ cnum room = c_num(minus(length_buf(srcbuf), offset));
+ if (offsn < 0)
+ uw_throwf(error_s, lit("~a: negative offset ~s specified"),
+ self, offset, nao);
+ if (room < tft->size)
+ uw_throwf(error_s, lit("~a: buffer ~s is too small for type ~s at offset ~s"),
+ self, srcbuf, type, offset, nao);
+ return tft->get(tft, src + offsn, self);
}
-val ffi_out(val dstbuf, val obj, val type, val copy_p)
+val ffi_out(val dstbuf, val obj, val type, val copy_p, val offset_in)
{
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(error_s, lit("~a: buffer ~s is too small for type ~s"),
- self, dstbuf, type, nao);
+ val offset = default_arg(offset_in, zero);
+ cnum offsn = c_num(offset);
+ cnum room = c_num(minus(length_buf(dstbuf), offset));
+ if (offsn < 0)
+ uw_throwf(error_s, lit("~a: negative offset ~s specified"),
+ self, offset, nao);
+ if (room < tft->size)
+ uw_throwf(error_s, lit("~a: buffer ~s is too small for type ~s at offset ~s"),
+ self, dstbuf, type, offset, nao);
if (tft->out != 0)
- tft->out(tft, copy_p != nil, obj, dst, self);
+ tft->out(tft, copy_p != nil, obj, dst + offsn, self);
else
- tft->put(tft, obj, dst, self);
+ tft->put(tft, obj, dst + offsn, self);
return dstbuf;
}
@@ -5538,11 +5562,11 @@ void ffi_init(void)
reg_fun(intern(lit("ffi-arraysize"), user_package), func_n1(ffi_arraysize));
reg_fun(intern(lit("ffi-elemsize"), user_package), func_n1(ffi_elemsize));
reg_fun(intern(lit("ffi-elemtype"), user_package), func_n1(ffi_elemtype));
- reg_fun(intern(lit("ffi-put-into"), user_package), func_n3(ffi_put_into));
+ reg_fun(intern(lit("ffi-put-into"), user_package), func_n4o(ffi_put_into, 3));
reg_fun(intern(lit("ffi-put"), user_package), func_n2(ffi_put));
- reg_fun(intern(lit("ffi-in"), user_package), func_n4(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_fun(intern(lit("ffi-in"), user_package), func_n5o(ffi_in, 4));
+ reg_fun(intern(lit("ffi-get"), user_package), func_n3o(ffi_get, 2));
+ reg_fun(intern(lit("ffi-out"), user_package), func_n5o(ffi_out, 4));
reg_fun(intern(lit("carrayp"), user_package), func_n1(carrayp));
reg_fun(intern(lit("carray-set-length"), user_package), func_n2(carray_set_length));
reg_fun(intern(lit("carray-dup"), user_package), func_n1(carray_dup));
diff --git a/ffi.h b/ffi.h
index 33ee549a..9d244885 100644
--- a/ffi.h
+++ b/ffi.h
@@ -85,11 +85,11 @@ val ffi_offsetof(val type, val memb);
val ffi_arraysize(val type);
val ffi_elemsize(val type);
val ffi_elemtype(val type);
-val ffi_put_into(val dstbuf, val obj, val type);
+val ffi_put_into(val dstbuf, val obj, val type, val offset);
val ffi_put(val obj, val type);
-val ffi_in(val srcbuf, val obj, val type, val copy_p);
-val ffi_get(val srcbuf, val type);
-val ffi_out(val dstbuf, val obj, val type, val copy_p);
+val ffi_in(val srcbuf, val obj, val type, val copy_p, val offset);
+val ffi_get(val srcbuf, val type, val offset);
+val ffi_out(val dstbuf, val obj, val type, val copy_p, val offset);
val make_carray(val type, mem_t *data, cnum nelem, val ref, cnum offs);
val carrayp(val obj);
val carray_set_length(val carray, val nelem);
diff --git a/txr.1 b/txr.1
index 3dd53160..1c2d23da 100644
--- a/txr.1
+++ b/txr.1
@@ -57457,7 +57457,7 @@ type.
.coNP Functions @ ffi-put and @ ffi-put-into
.synb
.mets (ffi-put < obj << type )
-.mets (ffi-put-into < dst-buf < obj << type )
+.mets (ffi-put-into < dst-buf < obj < type <> [ offset ])
.syne
.desc
The
@@ -57486,6 +57486,14 @@ argument must be an object compatible with the conversions
implied by
.metn type .
+The optional
+.meta offset
+argument specifies a byte offset from the beginning of the data area of
+.meta dst-buf
+where the foreign-representation of
+.meta obj
+is stored. The default value is zero.
+
These functions perform the "put semantics" encoding action very similar to
what happens to the arguments of an outgoing foreign function call.
@@ -57565,7 +57573,7 @@ replacement.
.coNP Function @ ffi-get
.synb
-.mets (ffi-get < src-buf << type )
+.mets (ffi-get < src-buf < type <> [ offset ])
.syne
.desc
The
@@ -57579,14 +57587,20 @@ The
argument is an object of type
.meta buf
large enough to hold a foreign representation of
-.metn type .
+.metn type ,
+at the byte offset indicated by the
+.meta offset
+argument.
The
.meta type
argument is compiled FFI type.
+The optional
+.meta offset
+argument defaults to zero.
The external representation in
.meta src-buf
-is scanned according to
+at the specified offset is scanned according to
.meta type
and converted to a Lisp value which is returned.