diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-29 12:12:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-29 12:12:20 -0700 |
commit | cced80ab687b521a1d07e53e1be70a33ea711d0f (patch) | |
tree | 243d5940f0f3a7e12662662dd994c45bba31da94 | |
parent | a77610707ca983a74e4f0af8926d663fdb71ecbf (diff) | |
download | txr-cced80ab687b521a1d07e53e1be70a33ea711d0f.tar.gz txr-cced80ab687b521a1d07e53e1be70a33ea711d0f.tar.bz2 txr-cced80ab687b521a1d07e53e1be70a33ea711d0f.zip |
ffi: zarray type for null terminated array support.
A zarray is null terminated when we convert from Lisp
to C representation. The last element of the Lisp vector
is ignored and all zero bits are written to the destination
buffer in the size of the element.
* ffi.c (zarray_s): New symbol variable.
(struct txr_ffi_type): New bitfield member, null_term.
(ffi_array_in): If the array's null_term flag is set,
then don't process the last element, since the corresponding
put call wasn't done for that element in ffi_array_put.
(ffi_array_put): If the array's null_term flag is set,
then when processing the last element, just memset the
output element to zero and don't call put.
(ffi_type_compile): Recognize zarray_s and set up the
flag accordingly.
(ffi_init): Initialize zarray_s.
* ffi.h (zarray_s): Declared.
-rw-r--r-- | ffi.c | 22 | ||||
-rw-r--r-- | ffi.h | 2 |
2 files changed, 20 insertions, 4 deletions
@@ -64,7 +64,7 @@ val long_s, ulong_s; val double_s; -val array_s; +val array_s, zarray_s; val void_s; @@ -87,6 +87,7 @@ struct txr_ffi_type { cnum size, align; cnum nelem; int rtidx, rtsize; + unsigned null_term : 1; void (*walk)(struct txr_ffi_type *, mem_t *ctx, void (*visit)(struct txr_ffi_type *, mem_t *ctx)); void (*put)(struct txr_ffi_type *, val obj, mem_t *dst, @@ -880,6 +881,8 @@ static void ffi_array_in(struct txr_ffi_type *tft, val obj, for (i = 0; i < nelem; i++) { val eltype = pop(&eltypes); struct txr_ffi_type *etft = ffi_type_struct(eltype); + if (i == nelem - 1 && tft->null_term) + break; if (etft->in != 0) etft->in(etft, obj, rtvec, self); } @@ -890,6 +893,7 @@ static void ffi_array_put(struct txr_ffi_type *tft, val vec, mem_t *dst, { val eltypes = tft->mtypes; cnum nelem = tft->nelem, i; + int nt = tft->null_term; ucnum offs = 0; for (i = 0; i < nelem; i++) { @@ -897,6 +901,10 @@ static void ffi_array_put(struct txr_ffi_type *tft, val vec, mem_t *dst, struct txr_ffi_type *etft = ffi_type_struct(eltype); cnum elsize = etft->size; val elval = ref(vec, num_fast(i)); + if (nt && i == nelem - 1) { + memset(dst + offs, 0, elsize); + break; + } etft->put(etft, elval, dst + offs, rtvec, self); offs += elsize; } @@ -1154,14 +1162,21 @@ val ffi_type_compile(val syntax) val xsyntax = cons(struct_s, cons(sname, membs)); return make_ffi_type_struct(xsyntax, stype, slots, types); - } else if (sym == array_s) { + } else if (sym == array_s || sym == zarray_s) { val dim = cadr(syntax); val eltype_syntax = caddr(syntax); list_collect_decl (eltypes, ptail); cnum dimn = c_num(dim), i; for (i = 0; i < dimn; i++) ptail = list_collect(ptail, ffi_type_compile(eltype_syntax)); - return make_ffi_type_array(syntax, eltypes, dim, eltypes); + + { + val type = make_ffi_type_array(syntax, eltypes, dim, eltypes); + struct txr_ffi_type *tft = ffi_type_struct(type); + if (sym == zarray_s) + tft->null_term = 1; + return type; + } } else if (sym == ptr_in_s) { val target_type = ffi_type_compile(cadr(syntax)); return make_ffi_type_pointer(syntax, cptr_s, sizeof (mem_t *), @@ -1517,6 +1532,7 @@ void ffi_init(void) ulong_s = intern(lit("ulong"), user_package); double_s = intern(lit("double"), user_package); array_s = intern(lit("array"), user_package); + zarray_s = intern(lit("zarray"), user_package); void_s = intern(lit("void"), user_package); struct_s = intern(lit("struct"), user_package); str_d_s = intern(lit("str-d"), user_package); @@ -43,7 +43,7 @@ extern val buf_d_s; extern val ptr_in_s, ptr_out_s, ptr_in_d_s, ptr_out_d_s, ptr_s; -extern val array_s; +extern val array_s, zarray_s; extern val void_s; |