summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-19 21:27:31 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-19 21:27:31 -0700
commit5a45245e056a1ac173f25d9d455ef322e9331739 (patch)
tree887709bb078dfacaef889f473e6037d7b0ce89fc /ffi.c
parent4bd2764b9df28cda6da92aa1eef3ac958ffcf459 (diff)
downloadtxr-5a45245e056a1ac173f25d9d455ef322e9331739.tar.gz
txr-5a45245e056a1ac173f25d9d455ef322e9331739.tar.bz2
txr-5a45245e056a1ac173f25d9d455ef322e9331739.zip
ffi: implement get for null terminated varrays.
* ffi.c (ffi_varray_null_term_get): New static function. (ffi_type_compile): Install the new get function for variable length zarray.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/ffi.c b/ffi.c
index c916ad8f..0f0129dc 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1345,6 +1345,35 @@ static val ffi_varray_in(struct txr_ffi_type *tft, int copy, mem_t *src,
return ffi_array_in_common(tft, copy, src, vec, self, nelem);
}
+static val ffi_varray_null_term_get(struct txr_ffi_type *tft, mem_t *src,
+ val self)
+{
+ val vec = vector(zero, nil);
+ val eltype = tft->mtypes;
+ struct txr_ffi_type *etft = ffi_type_struct(eltype);
+ cnum elsize = etft->size;
+ cnum offs, i;
+
+ for (i = 0, offs = 0; ; i++) {
+ mem_t *el = src + offs, *p;
+
+ for (p = el; p < el + elsize; p++)
+ if (*p)
+ break;
+
+ if (p == el + elsize)
+ break;
+
+ {
+ val elval = etft->get(etft, src + offs, self);
+ vec_push(vec, elval);
+ offs += elsize;
+ }
+ }
+
+ return vec;
+}
+
static void ffi_varray_release(struct txr_ffi_type *tft, val vec, mem_t *dst)
{
cnum nelem = c_num(length(vec)) + tft->null_term;
@@ -1591,8 +1620,10 @@ val ffi_type_compile(val syntax)
uw_throwf(error_s,
lit("~a: incomplete type ~s cannot be array element"),
self, eltype_syntax, nao);
- if (sym == zarray_s)
+ if (sym == zarray_s) {
tft->null_term = 1;
+ tft->get = ffi_varray_null_term_get;
+ }
tft->alloc = ffi_varray_alloc;
tft->free = free;
tft->size = 0;