diff options
-rw-r--r-- | ffi.c | 76 | ||||
-rw-r--r-- | ffi.h | 8 | ||||
-rw-r--r-- | txr.1 | 22 |
3 files changed, 72 insertions, 34 deletions
@@ -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)); @@ -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); @@ -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. |