summaryrefslogtreecommitdiffstats
path: root/buf.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-06-14 07:11:20 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-06-14 07:11:20 -0700
commitfdbd49a83ce4a567824c2830e202735d59b55a84 (patch)
tree8a72fe8ba353ce560458c0717b7f42fa43fd3f1d /buf.c
parent3d685d1985cd06cb0bcbb53cca66ab3239f4ea06 (diff)
downloadtxr-fdbd49a83ce4a567824c2830e202735d59b55a84.tar.gz
txr-fdbd49a83ce4a567824c2830e202735d59b55a84.tar.bz2
txr-fdbd49a83ce4a567824c2830e202735d59b55a84.zip
buffers: support negative indexing from end.
* buf.c (buf_check_index): Take struct buf p * parameter, to be able to displace negative values using the buffer length. (buf_put_bytes, buf_put_i8, puf_put_u8, but_put_char, buf_put_uchar, buf_get_bytes, buf_get_i8, buf_get_u8, buf_strm_get_byte_callback): Pass struct buf pointer to buf_check_index. In buf_put_bytes, we use the returned value instead of the original pos. (buf_strm_seek): Don't use buf_check_index for validating the position, since the negative indexing logic doesn't apply to stream seek operations.
Diffstat (limited to 'buf.c')
-rw-r--r--buf.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/buf.c b/buf.c
index 00babdf9..7d41d336 100644
--- a/buf.c
+++ b/buf.c
@@ -64,10 +64,12 @@ static cnum buf_check_alloc_size(val alloc_size, cnum len, val self)
return ah;
}
-static cnum buf_check_index(val index, val self)
+static cnum buf_check_index(struct buf *b, val index, val self)
{
cnum ix = c_num(index);
if (ix < 0)
+ ix = c_num(plus(b->len, index));
+ if (ix < 0)
uw_throwf(error_s, lit("~a: negative byte index ~s specified"),
self, index, nao);
return ix;
@@ -363,8 +365,8 @@ val replace_buf(val buf, val items, val from, val to)
static void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
{
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
- val req_len = plus(pos, num(size));
+ cnum p = buf_check_index(b, pos, self);
+ val req_len = plus(num(p), num(size));
if (gt(req_len, b->len))
buf_do_set_len(buf, b, req_len, nil, self);
memcpy(b->data + p, ptr, size);
@@ -375,7 +377,7 @@ val buf_put_i8(val buf, val pos, val num)
{
val self = lit("buf-put-i8");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
i8_t v = c_i8(num, self);
if (p >= c_num(b->len))
buf_do_set_len(buf, b, succ(pos), nil, self);
@@ -387,7 +389,7 @@ val buf_put_u8(val buf, val pos, val num)
{
val self = lit("buf-put-u8");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
cnum v = c_u8(num, self);
if (p >= c_num(b->len))
buf_do_set_len(buf, b, succ(pos), nil, self);
@@ -454,7 +456,7 @@ val buf_put_char(val buf, val pos, val num)
{
val self = lit("buf-put-char");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
char v = c_char(num, self);
if (p >= c_num(b->len))
buf_do_set_len(buf, b, succ(pos), nil, self);
@@ -466,7 +468,7 @@ val buf_put_uchar(val buf, val pos, val num)
{
val self = lit("buf-put-uchar");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
unsigned char v = c_uchar(num, self);
if (p >= c_num(b->len))
buf_do_set_len(buf, b, succ(pos), nil, self);
@@ -555,7 +557,7 @@ val buf_put_cptr(val buf, val pos, val cptr)
static void buf_get_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
{
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
cnum e = p + size;
cnum l = c_num(b->len);
@@ -570,7 +572,7 @@ val buf_get_i8(val buf, val pos)
{
val self = lit("buf-get-i8");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
if (p >= c_num(b->len))
uw_throwf(error_s, lit("~a: attempted read past buffer end"), self, nao);
return num_fast(convert(i8_t, b->data[p]));
@@ -580,7 +582,7 @@ val buf_get_u8(val buf, val pos)
{
val self = lit("buf-get-u8");
struct buf *b = buf_handle(buf, self);
- cnum p = buf_check_index(pos, self);
+ cnum p = buf_check_index(b, pos, self);
if (p >= c_num(b->len))
uw_throwf(error_s, lit("~a: attempted read past buffer end"), self, nao);
return num_fast(convert(u8_t, b->data[p]));
@@ -851,7 +853,7 @@ static int buf_strm_get_byte_callback(mem_t *ctx)
val self = lit("get-byte");
struct buf_strm *s = coerce(struct buf_strm *, ctx);
struct buf *b = buf_handle(s->buf, self);
- cnum p = buf_check_index(s->pos, self);
+ cnum p = buf_check_index(b, s->pos, self);
s->pos = num(p + 1);
return (p >= c_num(b->len)) ? EOF : b->data[p];
}
@@ -914,6 +916,7 @@ static val buf_strm_seek(val stream, val offset, enum strm_whence whence)
{
val self = lit("seek-stream");
struct buf_strm *s = coerce(struct buf_strm *, stream->co.handle);
+ struct buf *b = buf_handle(s->buf, self);
val npos;
switch (whence) {
@@ -926,16 +929,15 @@ static val buf_strm_seek(val stream, val offset, enum strm_whence whence)
npos = plus(s->pos, offset);
break;
case strm_end:
- {
- struct buf *b = buf_handle(s->buf, self);
- npos = minus(b->len, offset);
- }
+ npos = minus(b->len, offset);
break;
default:
internal_error("invalid whence value");
}
- (void) buf_check_index(npos, self);
+ if (minusp(npos))
+ uw_throwf(error_s, lit("~a: cannot seek to negative position ~s"),
+ self, index, nao);
s->pos = npos;
return t;