summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-07-09 17:21:16 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-07-09 17:21:16 -0700
commit3cba6501c6b20ca5da11b62da35a313bd557d094 (patch)
treeca61a7b6b1f718feedb456b96ccfad99a15cbd93
parente7698eff01592fc39953836bbe896444587e7f8b (diff)
downloadtxr-3cba6501c6b20ca5da11b62da35a313bd557d094.tar.gz
txr-3cba6501c6b20ca5da11b62da35a313bd557d094.tar.bz2
txr-3cba6501c6b20ca5da11b62da35a313bd557d094.zip
ffi: new function, zero-fill.
* ffi.c (zero_fill): New function. (ffi_init): zero-fill intrinsic registered. * ffi.h (zero_fill): Declared. * txr.1: Documented.
-rw-r--r--ffi.c33
-rw-r--r--ffi.h1
-rw-r--r--txr.134
3 files changed, 67 insertions, 1 deletions
diff --git a/ffi.c b/ffi.c
index 362218d5..9d1163f5 100644
--- a/ffi.c
+++ b/ffi.c
@@ -5406,6 +5406,38 @@ val make_zstruct(val type, struct args *args)
return strct;
}
+val zero_fill(val type, val obj)
+{
+ val self = lit("zero-fill");
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ cnum size = tft->size;
+ int need_free = (size >= 1024);
+ mem_t *buf = if3(need_free, chk_calloc(1, size), coerce(mem_t *, zalloca(size)));
+ val ret = nil;
+
+ if (need_free) {
+ uw_simple_catch_begin;
+
+ if (tft->in != 0)
+ ret = tft->in(tft, 1, buf, obj, self);
+ else
+ ret = tft->get(tft, buf, self);
+
+ uw_unwind {
+ free(buf);
+ }
+
+ uw_catch_end;
+ } else {
+ if (tft->in != 0)
+ ret = tft->in(tft, 1, buf, obj, self);
+ else
+ ret = tft->get(tft, buf, self);
+ }
+
+ return ret;
+}
+
void ffi_init(void)
{
prot1(&ffi_typedef_hash);
@@ -5533,6 +5565,7 @@ void ffi_init(void)
reg_fun(intern(lit("union-in"), user_package), func_n3(union_in));
reg_fun(intern(lit("union-out"), user_package), func_n3(union_out));
reg_fun(intern(lit("make-zstruct"), user_package), func_n1v(make_zstruct));
+ reg_fun(intern(lit("zero-fill"), user_package), func_n2(zero_fill));
ffi_typedef_hash = make_hash(nil, nil, nil);
ffi_init_types();
ffi_init_extra_types();
diff --git a/ffi.h b/ffi.h
index 7f5397e2..880ee2d3 100644
--- a/ffi.h
+++ b/ffi.h
@@ -131,4 +131,5 @@ val union_put(val uni, val memb, val newval);
val union_in(val uni, val memb, val memb_obj);
val union_out(val uni, val memb, val memb_obj);
val make_zstruct(val type, struct args *args);
+val zero_fill(val type, val obj);
void ffi_init(void);
diff --git a/txr.1 b/txr.1
index 368952db..17356843 100644
--- a/txr.1
+++ b/txr.1
@@ -57082,7 +57082,14 @@ following equivalence holds:
(ffi expr) <--> (ffi-type-compile 'expr)
.cble
-.SS* Zero-filled Struct Initialization
+.SS* Zero-filled Object Support
+
+Communicating with foreign interfaces sometimes requires representations
+to be initialized consisting of all zero bits, or mostly zero bits.
+
+\*(TX provides convenient ways to prepare Lisp objects such that when those
+objects are converted to a foreign representation, they generate zero-filled
+representations.
.coNP Function @ make-zstruct
.synb
@@ -57206,6 +57213,31 @@ the following results are observed:
(znew foo b 42) -> #S(foo a #<cptr bar: 0> b 42 c nil)
.cble
+.coNP Function @ zero-fill
+.synb
+.mets (zero-fill < type << obj )
+.syne
+.desc
+The
+.code zero-fill
+function invokes the by-reference in semantics of FFI type
+.meta type
+against a zero-filled buffer, and a Lisp object
+.metn obj .
+
+This means that if
+.meta obj
+is an aggregate such as a vector, list or structure,
+it is updated as if from an all-zero-bit foreign representation.
+In that situation,
+.meta obj
+is also returned.
+
+An object which has by-value semantics, such as an integer,
+is not updated. In this case, nevertheless, the return value
+is a Lisp object produced by converting an all-zero-bit buffer to
+.metn type .
+
.SS* Foreign Unions
The following group of functions provides the means for working