summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c46
-rw-r--r--ffi.h4
-rw-r--r--txr.132
3 files changed, 61 insertions, 21 deletions
diff --git a/ffi.c b/ffi.c
index 4aa67d89..f06d524f 100644
--- a/ffi.c
+++ b/ffi.c
@@ -2606,7 +2606,7 @@ static void ffi_varray_release(struct txr_ffi_type *tft, val vec, mem_t *dst)
static val ffi_carray_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
mem_t *p = *coerce(mem_t **, src);
- return make_carray(tft->eltype, p, -1, nil);
+ return make_carray(tft->eltype, p, -1, nil, 0);
}
static void ffi_carray_put(struct txr_ffi_type *tft, val carray, mem_t *dst,
@@ -4544,6 +4544,7 @@ struct carray {
mem_t *data;
cnum nelem;
val ref;
+ cnum offs;
val artype;
};
@@ -4597,7 +4598,7 @@ static struct cobj_ops carray_owned_ops =
carray_mark_op,
cobj_eq_hash_op);
-val make_carray(val type, mem_t *data, cnum nelem, val ref)
+val make_carray(val type, mem_t *data, cnum nelem, val ref, cnum offs)
{
struct carray *scry = coerce(struct carray *, chk_malloc(sizeof *scry));
val obj;
@@ -4610,6 +4611,7 @@ val make_carray(val type, mem_t *data, cnum nelem, val ref)
obj = cobj(coerce(mem_t *, scry), carray_s, &carray_borrowed_ops);
scry->eltype = type;
scry->ref = ref;
+ scry->offs = offs;
return obj;
}
@@ -4708,7 +4710,7 @@ val length_carray(val carray)
val copy_carray(val carray)
{
struct carray *scry = carray_struct_checked(carray);
- val copy = make_carray(scry->eltype, scry->data, scry->nelem, nil);
+ val copy = make_carray(scry->eltype, scry->data, scry->nelem, nil, 0);
carray_dup(copy);
return copy;
}
@@ -4765,24 +4767,34 @@ val carray_blank(val nelem, val type)
uw_throwf(error_s, lit("~a: negative array size"), self, nao);
} else {
mem_t *data = chk_calloc(nel, tft->size);
- val carray = make_carray(type, data, nel, nil);
+ val carray = make_carray(type, data, nel, nil, 0);
carray->co.ops = &carray_owned_ops;
return carray;
}
}
-val carray_buf(val buf, val type)
+val carray_buf(val buf, val type, val offs_in)
{
val self = lit("carray-buf");
mem_t *data = buf_get(buf, self);
- cnum blen = c_num(length_buf(buf));
+ val offs = default_arg_strict(offs_in, zero);
+ cnum offsn = c_num(offs);
+ cnum blen = c_num(minus(length_buf(buf), offs));
struct txr_ffi_type *tft = ffi_type_struct(type);
cnum nelem = if3(tft->size, blen / tft->size, 0);
+ if (offsn < 0)
+ uw_throwf(error_s,
+ lit("~a: negative offset ~s not permitted"),
+ self, offs, nao);
+ if (blen < 0)
+ uw_throwf(error_s,
+ lit("~a: offset ~s past end of buffer ~s"),
+ self, offs, buf, nao);
if (tft->size == 0)
uw_throwf(error_s,
lit("~a: incomplete type ~s cannot be carray element"),
self, tft->syntax, nao);
- return make_carray(type, data, nelem, buf);
+ return make_carray(type, data + offsn, nelem, buf, offsn);
}
val carray_buf_sync(val carray)
@@ -4791,10 +4803,14 @@ val carray_buf_sync(val carray)
struct carray *scry = carray_struct_checked(carray);
val buf = scry->ref;
mem_t *data = buf_get(buf, self);
- cnum blen = c_num(length_buf(buf));
+ cnum blen = c_num(minus(length_buf(buf), num(scry->offs)));
struct txr_ffi_type *tft = ffi_type_struct(scry->eltype);
+ if (blen < 0)
+ uw_throwf(error_s,
+ lit("~a: offset ~s past end of buffer ~s"),
+ self, num(scry->offs), buf, nao);
scry->nelem = blen / tft->size;
- scry->data = data;
+ scry->data = data + scry->offs;
return buf;
}
@@ -4803,7 +4819,7 @@ val carray_cptr(val cptr, val type, val len)
mem_t *data = cptr_get(cptr);
cnum nelem = c_num(default_arg(len, negone));
(void) ffi_type_struct(type);
- return make_carray(type, data, nelem, nil);
+ return make_carray(type, data, nelem, nil, 0);
}
val vec_carray(val carray, val null_term_p)
@@ -4909,7 +4925,7 @@ val carray_sub(val carray, val from, val to)
if (tn < fn)
tn = fn;
- return make_carray(scry->eltype, scry->data + fn * elsize, tn - fn, carray);
+ return make_carray(scry->eltype, scry->data + fn * elsize, tn - fn, carray, 0);
}
}
@@ -5096,7 +5112,7 @@ val carray_pun(val carray, val type)
if (len != 0 && size / elsize != len)
uw_throwf(error_s, lit("~a: array size overflow"), self, nao);
- return make_carray(type, scry->data, size / tft->size, carray);
+ return make_carray(type, scry->data, size / tft->size, carray, 0);
}
val carray_unum(val num, val eltype_in)
@@ -5125,7 +5141,7 @@ val carray_unum(val num, val eltype_in)
ucnum nelem = (size + tft->size - 1) / tft->size;
mem_t *data = chk_xalloc(nelem, tft->size, self);
ucnum delta = nelem * tft->size - size;
- val ca = make_carray(eltype, data, nelem, nil);
+ val ca = make_carray(eltype, data, nelem, nil, 0);
memset(data, 0, delta);
mp_to_unsigned_bin(m, data + delta);
gc_hint(num);
@@ -5165,7 +5181,7 @@ val carray_num(val num, val eltype_in)
ucnum nelem = (c_unum(bytes) + tft->size - 1) / tft->size;
mem_t *data = chk_xalloc(nelem, tft->size, self);
ucnum delta = nelem * tft->size - size;
- val ca = make_carray(eltype, data, nelem, nil);
+ val ca = make_carray(eltype, data, nelem, nil, 0);
mp_to_unsigned_bin(m, data + delta);
memset(data, if3(bit(ube, wi), 0xff, 0), delta);
gc_hint(num);
@@ -5538,7 +5554,7 @@ void ffi_init(void)
reg_fun(intern(lit("carray-vec"), user_package), func_n3o(carray_vec, 2));
reg_fun(intern(lit("carray-list"), user_package), func_n3o(carray_list, 2));
reg_fun(intern(lit("carray-blank"), user_package), func_n2(carray_blank));
- reg_fun(intern(lit("carray-buf"), user_package), func_n2(carray_buf));
+ reg_fun(intern(lit("carray-buf"), user_package), func_n3o(carray_buf, 2));
reg_fun(intern(lit("carray-buf-sync"), user_package), func_n1(carray_buf_sync));
reg_fun(intern(lit("carray-cptr"), user_package), func_n3o(carray_cptr, 2));
reg_fun(intern(lit("vec-carray"), user_package), func_n2o(vec_carray, 1));
diff --git a/ffi.h b/ffi.h
index 880ee2d3..33ee549a 100644
--- a/ffi.h
+++ b/ffi.h
@@ -90,7 +90,7 @@ 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 make_carray(val type, mem_t *data, cnum nelem, val ref);
+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);
val carray_dup(val carray);
@@ -103,7 +103,7 @@ mem_t *carray_ptr(val carray, val type, val self);
val carray_vec(val vec, val type, val null_term_p);
val carray_list(val list, val type, val null_term_p);
val carray_blank(val nelem, val type);
-val carray_buf(val buf, val type);
+val carray_buf(val buf, val type, val offs);
val carray_buf_sync(val carray);
val carray_cptr(val cptr, val type, val len);
val vec_carray(val carray, val null_term_p);
diff --git a/txr.1 b/txr.1
index d55a2839..8fbe698d 100644
--- a/txr.1
+++ b/txr.1
@@ -57707,7 +57707,7 @@ function, and of
.coNP Function @ carray-buf
.synb
-.mets (carray-buf < buf << type )
+.mets (carray-buf < buf < type <> [ offset ])
.syne
.desc
The
@@ -57718,15 +57718,39 @@ object which refers to the storage provided and managed by the buffer object
.metn buf ,
providing a view of that storage, and manipulation thereof, as an array.
+The optional
+.meta offset
+parameter specifies an offset from the start of the buffer to the
+location which is interpreted as the start of the
+.codn carray ,
+which extends from that offset to the end of the buffer.
+
+The default value is zero: the
+.code carray
+covers the entire buffer.
+
+If a value is specified, it must be in the range zero to the length of
+.metn buf .
+
The
.meta type
argument must be a compiled FFI type whose size is nonzero.
-The bytewise length of
+
+The
+.code carray
+is overlaid onto the storage of
+.meta buf
+as follows:
+
+First,
+.meta offs
+is subtracted from the bytewise length of
.metn buf ,
as reported by
.code length-buf
-function ,
-is divided by the size of
+function to produce the effective length of the storage to be used for the array.
+
+The effective length is divided by the size of
.metn type ,
as reported by
.codn ffi-size .