summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-08-25 06:49:53 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-08-25 06:49:53 -0700
commit98ec48bea40e4e80d25b26c99fbe44fc3e98459f (patch)
tree1a1761e44db628144c7cab6210a175952ebda74e
parenta37665e615c504415d5425f71ce5af7b7175b3f2 (diff)
downloadtxr-98ec48bea40e4e80d25b26c99fbe44fc3e98459f.tar.gz
txr-98ec48bea40e4e80d25b26c99fbe44fc3e98459f.tar.bz2
txr-98ec48bea40e4e80d25b26c99fbe44fc3e98459f.zip
carray: allow displacement in carray-pun.
* ffi.c (carray_pun): Takes two new arguments to specify displacement and size. (ffi_init): Registration of carray-pun adjusted. * ffi.h (carray_pun): Declaration updated. * txr.1: Documented.
-rw-r--r--ffi.c26
-rw-r--r--ffi.h2
-rw-r--r--txr.147
3 files changed, 63 insertions, 12 deletions
diff --git a/ffi.c b/ffi.c
index 708dbbcb..b100d30f 100644
--- a/ffi.c
+++ b/ffi.c
@@ -5916,21 +5916,35 @@ val carray_putz(val carray, val seq)
return carray;
}
-val carray_pun(val carray, val type)
+val carray_pun(val carray, val type, val offset_in, val lim_in)
{
val self = lit("carray-pun");
struct carray *scry = carray_struct_checked(self, carray);
struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
- cnum len = scry->nelem;
- cnum elsize = scry->eltft->size;
- cnum size = (ucnum) len * (ucnum) elsize;
+ ucnum len = scry->nelem;
+ ucnum elsize = scry->eltft->size;
+ ucnum size = len * elsize;
+ ucnum off = if3(missingp(offset_in), 0, c_unum(offset_in, self));
+ ucnum lim = if3(missingp(lim_in), size - off, c_unum(lim_in, self));
carray_elem_check(tft, self);
if (len != 0 && size / elsize != len)
uw_throwf(error_s, lit("~a: carray size overflow"), self, nao);
- return make_carray(type, scry->data, size / tft->size, carray, 0);
+ if (off > size)
+ uw_throwf(error_s, lit("~a: ~s: offset ~a is out of bounds"),
+ self, carray, unum(off), nao);
+
+ if (off + lim < off)
+ uw_throwf(error_s, lit("~a: ~s: limit ~a from offset ~a wraps around"),
+ self, carray, unum(lim), unum(off), nao);
+
+ if (off + lim > size)
+ uw_throwf(error_s, lit("~a: ~s: limit ~a from offset ~a extends out of bounds"),
+ self, carray, unum(lim), unum(off), nao);
+
+ return make_carray(type, scry->data + off, lim / tft->size, carray, 0);
}
val carray_uint(val num, val eltype_in)
@@ -6750,7 +6764,7 @@ void ffi_init(void)
reg_fun(intern(lit("carray-getz"), user_package), func_n1(carray_getz));
reg_fun(intern(lit("carray-put"), user_package), func_n2(carray_put));
reg_fun(intern(lit("carray-putz"), user_package), func_n2(carray_putz));
- reg_fun(intern(lit("carray-pun"), user_package), func_n2(carray_pun));
+ reg_fun(intern(lit("carray-pun"), user_package), func_n4o(carray_pun, 2));
{
val ca_uint = func_n2o(carray_uint, 1);
val ca_int = func_n2o(carray_int, 1);
diff --git a/ffi.h b/ffi.h
index fbc9faad..4029f450 100644
--- a/ffi.h
+++ b/ffi.h
@@ -122,7 +122,7 @@ val carray_get(val carray);
val carray_getz(val carray);
val carray_put(val array, val seq);
val carray_putz(val array, val seq);
-val carray_pun(val carray, val type);
+val carray_pun(val carray, val type, val offset_in, val lim_in);
val carray_uint(val num, val type);
val carray_int(val num, val type);
val uint_carray(val carray);
diff --git a/txr.1 b/txr.1
index 3ca2f9f3..729c5dd3 100644
--- a/txr.1
+++ b/txr.1
@@ -80428,7 +80428,7 @@ itself.
.coNP Function @ carray-pun
.synb
-.mets (carray-pun < carray << type )
+.mets (carray-pun < carray < type >> [ offset <> [ size-limit ]])
.syne
.desc
The
@@ -80444,13 +80444,37 @@ The
.meta type
argument specifies the element type used by the returned aliasing array.
+If the
+.meta offset
+argument is specified, then the aliased view is displaced by that many
+bytes from the start of the
+.meta carray
+object. The
+.meta offset
+argument must not be larger than the bytewise length of the array,
+or an error exception is thrown. The bytewise length of the array
+is the product of the number of elements and the element size.
+The default value of
+.meta offset
+is zero: no displacement.
+
+If
+.meta size-limit
+is specified, it indicates the size, in bytes, of the aliased view.
+This limit must not be such that the aliased view would extend beyond the
+array, or an error exception is thrown. If omitted,
+.meta size-limit
+defaults to the entire remainder of the array, after the offset.
+The number of elements of the returned array are then calculated from
+.metn size-limit .
+
The
.code carray-pun
-function considers the byte size of the array, which is a product of
-the original length and element size. It then calculates how many elements of
+function calculates how many elements of
.meta type
-fit into this size. This value becomes the length of the aliasing array
-which is returned.
+fit into
+.metn size-limit .
+This value becomes the length of the aliasing array which is returned.
Since the returned aliasing array and the original refer to the same
storage, modifications performed in one view are reflected in the other.
@@ -80464,6 +80488,19 @@ is invoked on the aliasing array.
The meaning of the aliasing depends entirely on the bitwise representations of
the types involved.
+Note:
+.code carray-pun
+does not check whether
+.meta offset
+is a value that is suitably aligned for accessing elements of
+.metn type ;
+on some platforms that must be ensured.
+
+The
+.code carray-pun
+function may be invoked on an object that was itself returned by
+.codn carray-pun .
+
.coNP Functions @ carray-uint and @ carray-int
.synb
.mets (carray-uint < number <> [ type ])