diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-05-30 06:00:40 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-05-30 06:00:40 -0700 |
commit | b17df7c06379615e4d1d1f912d6e57fb125294d1 (patch) | |
tree | 30b0caffb4b784c622214e722b99f3d5133e9405 /buf.c | |
parent | edfe34e241aafe19e6b29840e18ce318a2d22d61 (diff) | |
download | txr-b17df7c06379615e4d1d1f912d6e57fb125294d1.tar.gz txr-b17df7c06379615e4d1d1f912d6e57fb125294d1.tar.bz2 txr-b17df7c06379615e4d1d1f912d6e57fb125294d1.zip |
buf: use C types in buf and buf_strm structures.
Using Lisp types for lengths, indices and buffer sizes
has been awkward due to all the conversions. The
code in buf.c and other code elsewhere that touches
buffers, overall improves when we revise this
decision. Mostly there are fewer conversion from
Lisp to C which require a type check and self symbol
for error diagnsotis, like c_unum(len, self).
In a few places, there are conversions in the other
direction that were not needed before, like
unum(b->len). These are simpler and faster.
* lib.h (struct buf): Members len and size change
from val to ucnum (pointer-sized unsigned integer).
* gc.c (mark_obj): No need to do anything with BUF any
more; it has no Lisp object references.
* buf.c (BUR_BORROWED): New preprocessor symbol. Because
the allocation size can no longer be nil to indicate that
the buffer is borrowed (the buffer object doesn't own
the memory) we use this value instead: the highest value
of the ucnum type.
(buf_check_alloc_size): len parameter changes from cnum
to ucnum. Defends against the BUF_BORROWED value.
(buf_check_index): Returns ucnum rather than cnum.
(err_oflow): NORETURN attribute added to prevent some spurious
compiler warnings.
(prepare_pattern): Drop c_unum conversion of len.
(make_buf): Some locals change from cnum to ucnum.
We lose an unnecessary conversion.
(init_borrowed_buf): Take len as ucnum rather than val.
Use BUF_BORROWED value for allocated size to indicate
borrowed status.
(make_borrowed_buf): Take len as ucnum.
(make_duplicate_buf, make_owned_buf): Take len as ucnum,
and take a self argument. Check for the size being
BUF_BORROWED and reject.
(make_ubuf): Parameter renamed. Lose a conversion from
ucnum to val.
(copy_buf): Check for allocated size being BUF_BORROWED
to distinguish the two cases, rather than it being nil
or not.
(buf_shrink): Simplifies: loses a C to Lisp integer
conversion, and no longer needs the local variable self.
(buf_trim): Reject borrowed buffers by noticing the
BUF_BORROWED value.
(buf_do_set_len): len param becomes ucnum. Two Lisp-to-C
integer conversiond disappear; one C-to-Lisp moves
elsewhere in the code.
(buf_set_length): Use buf_check_len to check and
convert incoming len to ucnum. This is an improvement
over the previous approach of letting buf_do_set_len
to just rely on c_num conversions and their generic
diagnostics.
(buf_free): Check for borrowed buffer by comparing
allocated size to BUF_BORROWED constant.
(length_buf): ucnum to Lisp conversion now required here.
(buf_alloc_size): Check for alloc_size being BUF_BORROWED
and convert that to a nil return value. When returning
an integer size, we need a conversion to a Lisp integer.
(sub_buf): Use self symbol rather than lit("sub") when
obtaining buffer handle. Use buf_check_len to validate
the length and convert to C type.
(replace_buf): Some cnum local variables become ucnum.
We need a very careful comparison of w and l because
w remains signed while l is unsigned.
(buf_list): Substantially rewritten. We don't calculate
the length of the sequence upfront, but extend the
buffer as we add the elements to it.
(buf_move_bytes): size parameter changes from cnum
to ucnum. Lisp arithmetic replaced with C arithmetic;
conversions eliminated.
(buf_put_buf): Conversion eliminated in call to buf_move_bytes.
(buf_put_bytes): Function reduced to wrapper for
but_move_bytes, since it is almost identical. The only
difference is that it performs memcpy rather than memmove
which is not worth a separate function.
(buf_put_i8, buf_put_u8, buf_put_char, buf_put_uchar,
buf_get_i8, buf_get_u8): Simplified with C arithmetic
and fewer conversions; cnum use replaced with ucnum.
(buf_get_bytes): size parameter goes from cnum to ucnum.
Overflow check for p + size addition added.
(buf_print): Two conversions removed.
(buf_str_sep): Conversion removed.
(struct buf_strm): pos member changes from val to ucnum.
(buf_strm_mark): Do not mark p->pos, no longer a Lisp object.
(buf_strm_put_byte_callback): Lisp arithmetic removed,
but a unum conversion is needed now in calling buf_put_uchar.
That could be eliminated by not using the public interface.
(buf_strm_get_byte_callback): Eliminate buf_check_index to
validate the stream position; we simply check it against
b->len. Becomes simple one liner.
(buf_strm_get_char): Local variable index renamd to pos.
Two conversions from and to Lisp eliminated, leaving
no conversions.
(buf_strm_unget_byte): Local variable p renamed to pos and
changes from cnum to ucnum. Two conversions eliminated
leaving no conversions.
(buf_strm_fill_buf): Conversions eliminated. Check for the
allocated size being BUF_BORROWED, in which case we
fall back on using the length. Lisp arithmetic eliminated.
(buf_strm_seek): Offset calculation done with C arithmetic
and bounds checks.
(buf_strm_truncate): Check incoming len with buf_check_len
and convert to ucnum. Lisp arithmetic and conversions
eliminated; buf_do_set_len used instead of public interface
buf_set_length.
(buf_strm_get_error): Use C comparison rather than ge
function, and convert to t or nil result.
(buf_strm_get_error_str): Bug: do not call errno_to_string
since buffers don't talk to an operating system API that
uses errno. The only error condition is eof. Thus,
return either "eof" or "no error".
(make_buf_stream): Initialize pos to 0 rather than Lisp zero.
(swap32, buf_str, str_buf, buf_int, buf_uint, int_buf,
uint_buf): Conversions eliminated; int_buf and uint_buf use
C multiplication by 8. We know this doesn't overflow because
the MPI bignums restrict the number of bits to something
countable by a word.
(buf_compress, buf_decompress, str_compress, str_decompress):
Conversions eliminated.
(buf_ash, buf_fash, buf_and, buf_test, buf_or, buf_xor,
buf_not, buf_trunc, buf_bitset, buf_bit, buf_zero_p,
buf_count_ones, binary_width, buf_xor_pattern): Make
necessary adjustments, adding and/or elimiating conversions.
* buf.h (make_borrowed_buf, init_borrowed_buf, make_owned_buf,
make_duplicate_buf, buf_put_bytes): Declarations updated.
* lib.c (equal, less): Conversions eliminated in BUF cases.
* eval.c (map_common): Add self argument to make_owned_buf call.
* chksum.c (chksum_ensure_buf): len param changes from cnum
to ucnum. Conversions eliminated and use of lt() switches
to C less-than operator.
(sha1_stream, sha1_buf, sha1, sha1_hash, sha1_end,
sha256_stream, sha256_buf, sha256, sha256_hash, sha256_end,
md5_stream, md5_buf, md5, md5_hash, md5_end): Adjustments:
conversions eliminated.
(crc32_buf): Conversion eliminated.
* genchksum.txr: Changes to chksum.c actually made here.
* ffi.c (ffi_buf_in, ffi_buf_get, ffi_buf_d_in,
ffi_buf_d_get, buf_carray, put_carray, fill_carray,
put_obj, get_obj): Simplified with removal of
conversions.
(fill_obj): Necessary adjustments, leaving same
number of conversions.
* hash.c (equal_hash): Remove conversion from BUF case.
* rand.c (make_random_state): Remove conversion of seed
to Lisp integer.
(random_buf): Pass self to make_owned_buf.
* strudel.c (strudel_unget_byte, strudel_fill_buf):
Coversions removed, streamlining code.
* stream.c (iobuf_get, iobuf_put): We cannot overload
the len field with serving as a linked list since it's
no longer a pointer. We instead use the struct any
union member, which has a next pointer for this purpose.
Because "t.next" overlaps with "b.size", and we must not
clobber the size field, we save "b.size" by copying it
into "b.len". When pulling buffers from the iobuf_free_list,
we restore b.size from b.len. For good measure, We
add a bug_unless assertion that the size is the expected
one. I ran into a test case failure while working on this
due to the size being clobbered to zero, and subsequent
I/O with that zero-sized buffer being interpreted as EOF.
Diffstat (limited to 'buf.c')
-rw-r--r-- | buf.c | 422 |
1 files changed, 225 insertions, 197 deletions
@@ -52,40 +52,64 @@ #include "txr.h" #include "buf.h" +#define BUF_BORROWED UINT_PTR_MAX + #define min(a, b) ((a) < (b) ? (a) : (b)) static struct buf *buf_handle(val buf, val ctx); -static cnum buf_check_len(val len, val self) +static ucnum buf_check_len(val len, val self) { - cnum l = c_num(len, self); - if (l < 0) + if (minusp(len)) { uw_throwf(error_s, lit("~a: negative length ~s specified"), self, len, nao); - return l; + } else { + ucnum l = c_unum(len, self); + + if (l == BUF_BORROWED) + uw_throwf(error_s, lit("~a: reserved length value ~s specified"), + self, len, nao); + + return l; + } } -static cnum buf_check_alloc_size(val alloc_size, cnum len, val self) +static ucnum buf_check_alloc_size(val alloc_size, ucnum len, val self) { - cnum ah = c_num(alloc_size, self); - if (ah < len) + ucnum as = c_unum(alloc_size, self); + + if (as == BUF_BORROWED) + uw_throwf(error_s, lit("~a: reserved alloc size value ~s specified"), + self, alloc_size, nao); + + if (as < len) uw_throwf(error_s, lit("~a: alloc size size ~s lower than length"), self, alloc_size, nao); - return ah; + + return as; } -static cnum buf_check_index(struct buf *b, val index, val self) +static ucnum buf_check_index(struct buf *b, val index_in, val self) { - cnum ix = c_num(index, self); - if (ix < 0) - ix = c_num(plus(b->len, index), self); - if (ix < 0) + val index = minusp(index_in) ? plus(unum(b->len), index_in) : index_in; + ucnum ix; + + if (minusp(index)) { uw_throwf(error_s, lit("~a: negative byte index ~s specified"), self, index, nao); + } + + ix = c_unum(index, self); + + if (ix >= BUF_BORROWED - 1) { + uw_throwf(error_s, lit("~a: index ~s disallowed"), + self, index, nao); + } + return ix; } -static void err_oflow(val self) +NORETURN static void err_oflow(val self) { uw_throwf(error_s, lit("~a: array size overflow"), self, nao); } @@ -137,7 +161,7 @@ static void prepare_pattern(mem_t **ppat, mem_t **pfree, mem_t pbuf[SIZEOF_PTR], case BUF: { struct buf *pb = buf_handle(pat, self); - ucnum l = c_unum(pb->len, self); + ucnum l = pb->len; if (l > 0) { *ppat = pb->data; @@ -157,9 +181,9 @@ val make_buf(val len, val init_pat, val alloc_size) { val self = lit("make-buf"); val pat = default_arg(init_pat, zero); - cnum blen = buf_check_len(len, self); + ucnum blen = buf_check_len(len, self); val alloc = if3(null_or_missing_p(alloc_size), len, alloc_size); - cnum size = buf_check_alloc_size(alloc, blen, self); + ucnum size = buf_check_alloc_size(alloc, blen, self); mem_t *data = if3(pat == zero && size == blen, chk_calloc(size, 1), chk_malloc(size)); @@ -168,8 +192,8 @@ val make_buf(val len, val init_pat, val alloc_size) obj->b.type = BUF; obj->b.data = data; - obj->b.len = len; - obj->b.size = num(size); + obj->b.len = blen; + obj->b.size = size; if ((is_num(pat) || is_chr(pat)) && -256 < (iv = c_num(pat, self)) && iv < 256) @@ -210,45 +234,51 @@ val bufp(val object) return tnil(type(object) == BUF); } -val init_borrowed_buf(obj_t *obj, val len, mem_t *data) +val init_borrowed_buf(obj_t *obj, ucnum len, mem_t *data) { obj->b.type = BUF; obj->b.data = data; obj->b.len = len; - obj->b.size = nil; + obj->b.size = BUF_BORROWED; return obj; } -val make_borrowed_buf(val len, mem_t *data) +val make_borrowed_buf(ucnum len, mem_t *data) { return init_borrowed_buf(make_obj(), len, data); } -val make_duplicate_buf(val len, mem_t *data) +val make_duplicate_buf(ucnum len, mem_t *data, val self) { - val self = lit("make-duplicate-buf"); - val obj = make_obj(); + if (len < BUF_BORROWED) { + val obj = make_obj(); - obj->b.type = BUF; - obj->b.data = chk_copy_obj(data, c_num(len, self)); - obj->b.len = len; - obj->b.size = len; + obj->b.type = BUF; + obj->b.data = chk_copy_obj(data, len); + obj->b.len = len; + obj->b.size = len; - return obj; + return obj; + } else { + err_oflow(self); + } } -val make_owned_buf(val len, mem_t *data) +val make_owned_buf(ucnum len, mem_t *data, val self) { - val buf = make_borrowed_buf(len, data); - buf->b.size = len; - return buf; + if (len < BUF_BORROWED) { + val buf = make_borrowed_buf(len, data); + buf->b.size = len; + return buf; + } else { + err_oflow(self); + } } -static val make_ubuf(ucnum clen) +static val make_ubuf(ucnum len) { - mem_t *data = chk_malloc(clen); - val len = unum(clen); + mem_t *data = chk_malloc(len); val buf = make_borrowed_buf(len, data); buf->b.size = len; return buf; @@ -269,22 +299,22 @@ INLINE struct buf *us_buf_handle(val buf) val copy_buf(val buf) { - struct buf *b = buf_handle(buf, lit("copy-buf")); - return if3(b->size, - make_duplicate_buf(b->len, b->data), + val self = lit("copy-buf"); + struct buf *b = buf_handle(buf, self); + return if3(b->size != BUF_BORROWED, + make_duplicate_buf(b->len, b->data, self), make_borrowed_buf(b->len, b->data)); } static void buf_shrink(struct buf *b) { - val self = lit("buf-trim"); - val len = b->len; + ucnum len = b->len; - if (len == zero) - len = succ(len); /* avoid reallocing to zero length; i.e. freeing */ + if (len == 0) + len = 1; /* avoid zero size realloc */ if (len != b->size) { - b->data = chk_realloc(b->data, c_unum(len, self)); + b->data = chk_realloc(b->data, len); b->size = b->len; } } @@ -293,27 +323,25 @@ val buf_trim(val buf) { val self = lit("buf-trim"); struct buf *b = buf_handle(buf, self); - val oldsize = b->size; - if (!oldsize) + ucnum oldsize = b->size; + if (oldsize == BUF_BORROWED) uw_throwf(error_s, lit("~a: ~s is a fixed buffer"), self, buf, nao); buf_shrink(b); - return oldsize; + return unum(oldsize); } -static val buf_do_set_len(val buf, struct buf *b, val newlen, +static val buf_do_set_len(val buf, struct buf *b, ucnum len, val init_pat, val self) { - val oldlen = b->len; - cnum olen = c_num(oldlen, self), len = c_num(newlen, self); - cnum oldsize = c_num(b->size, self), size = oldsize; + ucnum olen = b->len; + ucnum oldsize = b->size, size = oldsize; - if (!b->size) + if (b->size == BUF_BORROWED) uw_throwf(error_s, lit("~a: ~s is a fixed buffer"), self, buf, nao); - (void) buf_check_len(newlen, self); - b->len = newlen; + b->len = len; if (size < len) { if (size > INT_PTR_MAX - INT_PTR_MAX / 5) { @@ -327,7 +355,7 @@ static val buf_do_set_len(val buf, struct buf *b, val newlen, if (size > oldsize) { b->data = chk_realloc(b->data, size); - b->size = num(size); + b->size = size; } if (len > olen) { @@ -364,24 +392,24 @@ static val buf_do_set_len(val buf, struct buf *b, val newlen, } } - return oldlen; + return unum(olen); } val buf_set_length(val buf, val len, val init_val) { val self = lit("buf-set-len"); struct buf *b = buf_handle(buf, self); - return buf_do_set_len(buf, b, len, init_val, self); + ucnum l = buf_check_len(len, self); + return buf_do_set_len(buf, b, l, init_val, self); } val buf_free(val buf) { val self = lit("buf-free"); struct buf *b = buf_handle(buf, self); - if (b->size) { + if (b->size != BUF_BORROWED) { free(b->data); b->data = 0; - b->len = b->size = zero; return t; } return nil; @@ -391,14 +419,14 @@ val length_buf(val buf) { val self = lit("length-buf"); struct buf *b = buf_handle(buf, self); - return b->len; + return unum(b->len); } val buf_alloc_size(val buf) { val self = lit("buf-alloc-size"); struct buf *b = buf_handle(buf, self); - return b->size; + return b->size == BUF_BORROWED ? nil : unum(b->size); } mem_t *buf_get(val buf, val self) @@ -410,8 +438,8 @@ mem_t *buf_get(val buf, val self) val sub_buf(val buf, val from, val to) { val self = lit("sub-buf"); - struct buf *b = buf_handle(buf, lit("sub")); - val len = b->len; + struct buf *b = buf_handle(buf, self); + val len = unum(b->len); if (null_or_missing_p(from)) from = zero; @@ -436,7 +464,8 @@ val sub_buf(val buf, val from, val to) } else if (from == zero && to == len) { return buf; } else { - return make_duplicate_buf(minus(to, from), b->data + c_num(from, self)); + return make_duplicate_buf(buf_check_len(minus(to, from), self), + b->data + c_num(from, self), self); } } @@ -451,8 +480,8 @@ val replace_buf(val buf, val items, val from, val to) from = len; } else if (!integerp(from)) { seq_iter_t wh_iter, item_iter; - cnum offs = 0; - cnum l = c_num(len, self), ol = l; + ucnum offs = 0; + ucnum l = c_unum(len, self), ol = l; val wh, item; seq_iter_init(self, &wh_iter, from); seq_iter_init(self, &item_iter, items); @@ -480,7 +509,7 @@ val replace_buf(val buf, val items, val from, val to) w -= offs; - if (w >= l) + if (l <= INT_PTR_MAX && w >= convert(cnum, l)) break; memmove(buf->b.data + w, @@ -516,8 +545,8 @@ val replace_buf(val buf, val items, val from, val to) if (gt(len_rep, len_it)) { val len_diff = minus(len_rep, len_it); - cnum t = c_num(to, self); - cnum l = c_num(len, self); + ucnum t = c_unum(to, self); + ucnum l = c_unum(len, self); memmove(buf->b.data + t - c_num(len_diff, self), buf->b.data + t, @@ -527,8 +556,8 @@ val replace_buf(val buf, val items, val from, val to) to = plus(from, len_it); } else if (lt(len_rep, len_it)) { val len_diff = minus(len_it, len_rep); - cnum t = c_num(to, self); - cnum l = c_num(len, self); + ucnum t = c_unum(to, self); + ucnum l = c_unum(len, self); buf_set_length(buf, plus(len, len_diff), zero); @@ -544,8 +573,8 @@ val replace_buf(val buf, val items, val from, val to) memmove(buf->b.data + c_num(from, self), items->b.data, c_num(len_it, self)); } else { seq_iter_t item_iter; - cnum f = c_num(from, self); - cnum t = c_num(to, self); + ucnum f = c_unum(from, self); + ucnum t = c_unum(to, self); seq_iter_init(self, &item_iter, items); @@ -562,26 +591,29 @@ val replace_buf(val buf, val items, val from, val to) val buf_list(val list) { val self = lit("buf-list"); - val len = length(list); - val buf = make_buf(zero, zero, len); + val buf = make_buf(zero, zero, num_fast(32)); + struct buf *b = us_buf_handle(buf); seq_iter_t iter; val elem; - cnum i; - - for (i = 0, seq_iter_init(self, &iter, list); seq_get(&iter, &elem); i++) - buf->b.data[i] = c_uchar(elem, self); + ucnum i; - buf->b.len = len; + for (i = 0, seq_iter_init(self, &iter, list); seq_get(&iter, &elem); i++) { + if (i + 1 < i) + err_oflow(self); + buf_do_set_len(buf, b, i + 1, elem, self); + } return buf; } -static void buf_move_bytes(val buf, val pos, mem_t *ptr, cnum size, val self) +static void buf_move_bytes(val buf, val pos, mem_t *ptr, ucnum size, val self) { struct buf *b = buf_handle(buf, self); - cnum p = buf_check_index(b, pos, self); - val req_len = plus(num(p), num(size)); - if (gt(req_len, b->len)) + ucnum p = buf_check_index(b, pos, self); + ucnum req_len = p + size; + if (req_len < p) + err_oflow(self); + if (req_len > b->len) buf_do_set_len(buf, b, req_len, nil, self); memmove(b->data + p, ptr, size); } @@ -590,7 +622,7 @@ val buf_put_buf(val dbuf, val pos, val sbuf) { val self = lit("buf-put-buf"); struct buf *sb = buf_handle(sbuf, self); - buf_move_bytes(dbuf, pos, sb->data, c_num(sb->len, self), self); + buf_move_bytes(dbuf, pos, sb->data, sb->len, self); return sbuf; } @@ -602,14 +634,9 @@ static val compat_buf_put_buf(val dbuf, val pos, val sbuf) return buf_put_buf(dbuf, pos, sbuf); } -void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self) +void buf_put_bytes(val buf, val pos, mem_t *ptr, ucnum size, val self) { - struct buf *b = buf_handle(buf, self); - 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); + return buf_move_bytes(buf, pos, ptr, size, self); } #if HAVE_I8 @@ -617,10 +644,10 @@ 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(b, pos, self); + ucnum p = buf_check_index(b, pos, self); i8_t v = c_i8(num, self); - if (p >= c_num(b->len, self)) - buf_do_set_len(buf, b, succ(pos), nil, self); + if (p >= b->len) + buf_do_set_len(buf, b, p + 1, nil, self); b->data[p] = v; return num; } @@ -629,10 +656,10 @@ 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(b, pos, self); + ucnum p = buf_check_index(b, pos, self); cnum v = c_u8(num, self); - if (p >= c_num(b->len, self)) - buf_do_set_len(buf, b, succ(pos), nil, self); + if (p >= b->len) + buf_do_set_len(buf, b, p + 1, nil, self); b->data[p] = v; return num; } @@ -696,10 +723,10 @@ 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(b, pos, self); + ucnum p = buf_check_index(b, pos, self); char v = c_char(num, self); - if (p >= c_num(b->len, self)) - buf_do_set_len(buf, b, succ(pos), nil, self); + if (p >= b->len) + buf_do_set_len(buf, b, p + 1, nil, self); b->data[p] = v; return num; } @@ -708,10 +735,10 @@ 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(b, pos, self); + ucnum p = buf_check_index(b, pos, self); unsigned char v = c_uchar(num, self); - if (p >= c_num(b->len, self)) - buf_do_set_len(buf, b, succ(pos), nil, self); + if (p >= b->len) + buf_do_set_len(buf, b, p + 1, nil, self); b->data[p] = v; return num; } @@ -794,14 +821,17 @@ val buf_put_cptr(val buf, val pos, val cptr) return cptr; } -void buf_get_bytes(val buf, val pos, mem_t *ptr, cnum size, val self) +void buf_get_bytes(val buf, val pos, mem_t *ptr, ucnum size, val self) { struct buf *b = buf_handle(buf, self); - cnum p = buf_check_index(b, pos, self); - cnum e = p + size; - cnum l = c_num(b->len, self); + ucnum p = buf_check_index(b, pos, self); + ucnum e = p + size; + ucnum l = b->len; - if (e > l || e < 0) + if (e < p) + err_oflow(self); + + if (e > l) uw_throwf(error_s, lit("~a: attempted read past buffer end"), self, nao); memcpy(ptr, b->data + p, size); @@ -812,8 +842,8 @@ 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(b, pos, self); - if (p >= c_num(b->len, self)) + ucnum p = buf_check_index(b, pos, self); + if (p >= b->len) uw_throwf(error_s, lit("~a: attempted read past buffer end"), self, nao); return num_fast(convert(i8_t, b->data[p])); } @@ -822,8 +852,8 @@ 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(b, pos, self); - if (p >= c_num(b->len, self)) + ucnum p = buf_check_index(b, pos, self); + if (p >= b->len) uw_throwf(error_s, lit("~a: attempted read past buffer end"), self, nao); return num_fast(convert(u8_t, b->data[p])); } @@ -996,7 +1026,7 @@ val buf_print(val buf, val stream_in) val self = lit("buf-print"); val stream = default_arg(stream_in, std_output); struct buf *b = buf_handle(buf, self); - cnum len = c_num(b->len, self), count = 0; + ucnum len = b->len, count = 0; mem_t *data = b->data; val save_mode = test_neq_set_indent_mode(stream, num_fast(indent_foff), num_fast(indent_data)); @@ -1028,7 +1058,7 @@ val buf_pprint(val buf, val stream_in) val self = lit("buf-pprint"); val stream = default_arg(stream_in, std_output); struct buf *b = buf_handle(buf, self); - cnum len = c_num(b->len, self); + ucnum len = b->len; mem_t *data = b->data; if (opt_compat && opt_compat <= 294) { @@ -1045,7 +1075,7 @@ val buf_pprint(val buf, val stream_in) val buf_str_sep(val buf, val sep, val self) { struct buf *b = buf_handle(buf, self); - ucnum len = c_unum(b->len, self); + ucnum len = b->len; val ret = null_string; if (len > 0) { @@ -1085,7 +1115,7 @@ struct buf_strm { utf8_decoder_t ud; int is_byte_oriented; val buf; - val pos; + ucnum pos; }; static void buf_strm_mark(val stream) @@ -1093,14 +1123,13 @@ static void buf_strm_mark(val stream) struct buf_strm *b = coerce(struct buf_strm *, stream->co.handle); strm_base_mark(&b->a); gc_mark(b->buf); - gc_mark(b->pos); } static int buf_strm_put_byte_callback(int b, mem_t *ctx) { struct buf_strm *s = coerce(struct buf_strm *, ctx); - (void) buf_put_uchar(s->buf, s->pos, num_fast(b)); - s->pos = succ(s->pos); + (void) buf_put_uchar(s->buf, unum(s->pos), num_fast(b)); + s->pos++; return 1; } @@ -1134,12 +1163,9 @@ static val buf_strm_put_byte(val stream, int b) 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 = us_buf_handle(s->buf); - cnum p = buf_check_index(b, s->pos, self); - s->pos = num(p + 1); - return (p >= c_num(b->len, self)) ? EOF : b->data[p]; + return (s->pos >= b->len) ? EOF : b->data[s->pos++]; } static val buf_strm_get_char(val stream) @@ -1173,22 +1199,22 @@ static val buf_strm_unget_char(val stream, val ch) struct buf *b = us_buf_handle(s->buf); struct utf8_tiny_buf bu; unsigned char *bend = bu.buf + sizeof bu.buf; - ucnum index = c_unum(s->pos, self); + ucnum pos = s->pos; bu.ptr = bend; (void) utf8_encode(c_chr(ch), utf8_tiny_buf_putc, coerce(mem_t *, &bu)); - if (convert(size_t, bend - bu.ptr) > index) { + if (convert(size_t, bend - bu.ptr) > pos) { uw_throwf(file_error_s, lit("~a: cannot push back past start of stream ~s"), stream, self, nao); } while (bu.ptr < bend) - b->data[--index] = *bu.ptr++; + b->data[--pos] = *bu.ptr++; - s->pos = unum(index); + s->pos = pos; return ch; } @@ -1198,16 +1224,16 @@ static val buf_strm_unget_byte(val stream, int byte) val self = lit("unget-byte"); struct buf_strm *s = coerce(struct buf_strm *, stream->co.handle); struct buf *b = us_buf_handle(s->buf); - cnum p = c_num(s->pos, self); + ucnum pos = s->pos; - if (p <= 0) { + if (pos <= 0) { uw_throwf(file_error_s, lit("~a: cannot push back past start of stream ~s"), self, stream, nao); } - b->data[--p] = byte; - s->pos = num(p); + b->data[--pos] = byte; + s->pos = pos; return num_fast(byte); } @@ -1222,12 +1248,12 @@ static ucnum buf_strm_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos) if (pos >= len) { return len; } else { - size_t index = c_unum(s->pos, self); size_t room = len - pos; - size_t avail = c_u(b->size) - index; + size_t blen = b->size == BUF_BORROWED ? b->len : b->size; + size_t avail = blen - s->pos; size_t copy = min(room, avail); - memcpy(ptr + pos, b->data + index, copy); - s->pos = plus(s->pos, unum(copy)); + memcpy(ptr + pos, b->data + s->pos, copy); + s->pos += copy; return pos + copy; } } @@ -1238,31 +1264,35 @@ 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 = us_buf_handle(s->buf); - val npos; + cnum off = c_num(offset, self); + ucnum npos; + ucnum from; switch (whence) { case strm_start: - npos = offset; + from = 0; break; case strm_cur: - if (offset == zero) - return s->pos; - npos = plus(s->pos, offset); + if (off == 0) + return unum(s->pos); + from = s->pos; break; case strm_end: - npos = plus(b->len, offset); + from = b->len; break; default: internal_error("invalid whence value"); } + npos = from + off; - if (minusp(npos)) - uw_throwf(file_error_s, lit("~a: cannot seek to negative position ~s"), - self, npos, nao); + if ((off >= 0 && npos < from) || + (off < 0 && npos > from)) + uw_throwf(file_error_s, lit("~a: overflow in seeking ~s bytes from ~s"), + self, offset, unum(from), nao); - if (gt(npos, b->len)) - buf_set_length(s->buf, npos, zero); + if (npos > b->len) + buf_set_length(s->buf, unum(npos), zero); s->pos = npos; return t; @@ -1271,19 +1301,15 @@ static val buf_strm_seek(val stream, val offset, enum strm_whence whence) static val buf_strm_truncate(val stream, val len) { val self = lit("truncate-stream"); + ucnum blen = buf_check_len(len, self); struct buf_strm *s = coerce(struct buf_strm *, stream->co.handle); struct buf *b = us_buf_handle(s->buf); - if (ge(len, s->pos)) { - buf_set_length(s->buf, len, zero); - } else if (minusp(len)) { - uw_throwf(file_error_s, lit("~a: negative length~s specified"), - self, len, nao); + if (blen >= s->pos) { + buf_do_set_len(s->buf, b, blen, nil, self); } else { - cnum p = c_num(s->pos, self); - cnum l = c_num(len, self); - buf_set_length(s->buf, s->pos, zero); - memset(b->data + l, 0, p - l); + buf_do_set_len(s->buf, b, s->pos, nil, self); + memset(b->data + blen, 0, s->pos - blen); } return t; @@ -1319,12 +1345,12 @@ static val buf_strm_get_error(val stream) { struct buf_strm *s = coerce(struct buf_strm *, stream->co.handle); struct buf *b = us_buf_handle(s->buf); - return ge(s->pos, b->len); + return tnil(s->pos >= b->len); } static val buf_strm_get_error_str(val stream) { - return errno_to_string(buf_strm_get_error(stream)); + return buf_strm_get_error(stream) ? lit("eof") : lit("no error"); } static struct strm_ops buf_strm_ops = @@ -1378,7 +1404,7 @@ val make_buf_stream(val buf_opt) strm_base_init(&s->a); utf8_decoder_init(&s->ud); s->buf = nil; - s->pos = zero; + s->pos = 0; s->is_byte_oriented = 0; stream = cobj(coerce(mem_t *, s), stream_cls, &buf_strm_ops.cobj_ops); s->buf = buf; @@ -1397,7 +1423,7 @@ void buf_swap32(val buf) { val self = lit("buf-swap32"); struct buf *b = buf_handle(buf, self); - mem_t *data = b->data, *end = data + c_num(b->len, self); + mem_t *data = b->data, *end = data + b->len; for (; data + 3 < end; data += 4) { u32_t sw32 = *coerce(u32_t *, data); @@ -1413,7 +1439,7 @@ static val buf_str(val str, val null_term) size_t sz; val nt = default_null_arg(null_term); unsigned char *u8 = utf8_dup_to_buf(c_str(str, self), &sz, nt != nil); - return make_owned_buf(unum(sz), u8); + return make_owned_buf(sz, u8, self); } static val str_buf(val buf, val null_term) @@ -1421,8 +1447,8 @@ static val str_buf(val buf, val null_term) val self = lit("str-buf"); struct buf *b = buf_handle(buf, self); val nt = default_null_arg(null_term); - size_t blen = c_unum(b->len, self); - size_t len = (nt && blen > 0 && !b->data[blen-1]) ? blen - 1 : blen; + size_t blen = b->len; + size_t len = (nt && blen > 0 && !b->data[blen - 1]) ? blen - 1 : blen; wchar_t *str = utf8_dup_from_buf(coerce(const char *, b->data), len); return string_own(str); } @@ -1451,7 +1477,7 @@ static val buf_int(val num) mem_t *data = chk_malloc(bufsize); data[0] = 0; mp_to_unsigned_bin(m, data + (bufsize - numsize)); - return make_owned_buf(unum(bufsize), data); + return make_owned_buf(bufsize, data, self); } default: uw_throwf(type_error_s, lit("~a: ~s isn't an integer or character"), @@ -1476,7 +1502,7 @@ static val buf_uint(val num) size_t size = mp_unsigned_bin_size(m); mem_t *data = chk_malloc(size); mp_to_unsigned_bin(m, data); - return make_owned_buf(unum(size), data); + return make_owned_buf(size, data, self); } } uw_throwf(type_error_s, lit("~a: ~s isn't a non-negative integer"), @@ -1491,19 +1517,19 @@ static val int_buf(val buf) { val self = lit("int-buf"); struct buf *b = buf_handle(buf, self); - ucnum size = c_unum(b->len, self); + ucnum size = b->len; val ubn = make_bignum(); mp_err mpe = mp_read_unsigned_bin(mp(ubn), b->data, size); if (mpe != MP_OKAY) do_mp_error(self, mpe); - return sign_extend(normalize(ubn), mul(b->len, num_fast(8))); + return sign_extend(normalize(ubn), unum(b->len * 8)); } static val uint_buf(val buf) { val self = lit("uint-buf"); struct buf *b = buf_handle(buf, self); - ucnum size = c_unum(b->len, self); + ucnum size = b->len; val ubn = make_bignum(); mp_err mpe = mp_read_unsigned_bin(mp(ubn), b->data, size); if (mpe != MP_OKAY) @@ -1519,7 +1545,7 @@ static val buf_compress(val buf, val level_opt) val level = default_arg(level_opt, negone); int lev = c_int(level, self); struct buf *b = buf_handle(buf, self); - ucnum size = c_unum(b->len, self); + ucnum size = b->len; uLong bound = compressBound(size), zsize = bound; mem_t *zdata = chk_malloc(bound); @@ -1534,14 +1560,14 @@ static val buf_compress(val buf, val level_opt) } zdata = chk_realloc(zdata, zsize); - return make_owned_buf(unum(zsize), zdata); + return make_owned_buf(zsize, zdata, self); } static val buf_decompress(val buf) { val self = lit("buf-decompress"); struct buf *b = buf_handle(buf, self); - ucnum zsize = c_unum(b->len, self); + ucnum zsize = b->len; uLong zsz10 = 10 * zsize; uLong size = if3(zsz10 > zsize, zsz10, convert(uLong, -1)); mem_t *data = chk_malloc(size); @@ -1550,7 +1576,7 @@ static val buf_decompress(val buf) switch (uncompress(data, &size, b->data, zsize)) { case Z_OK: data = chk_realloc(data, size); - return make_owned_buf(unum(size), data); + return make_owned_buf(size, data, self); case Z_BUF_ERROR: if (size == convert(uLong, -1)) break; @@ -1593,14 +1619,14 @@ static val str_compress(val str, val level_opt) } zdata = chk_realloc(zdata, zsize); - return make_owned_buf(unum(zsize), zdata); + return make_owned_buf(zsize, zdata, self); } static val str_decompress(val buf) { val self = lit("str-decompress"); struct buf *b = buf_handle(buf, self); - ucnum zsize = c_unum(b->len, self); + ucnum zsize = b->len; uLong zsz10 = 10 * zsize; uLong size = if3(zsz10 > zsize, zsz10, convert(uLong, -1)); mem_t *data = chk_malloc(size); @@ -1642,7 +1668,7 @@ val buf_ash(val buf, val bits) val self = lit("buf-ash"); cnum b = c_num(bits, self); struct buf *bh = buf_handle(buf, self); - ucnum len = c_unum(bh->len, self); + ucnum len = bh->len; if (b == 0) { return buf; @@ -1721,7 +1747,7 @@ val buf_fash(val buf, val bits) val self = lit("buf-ash"); cnum b = c_num(bits, self); struct buf *bh = buf_handle(buf, self); - ucnum len = c_unum(bh->len, self); + const ucnum len = bh->len; if (b == 0 || len == 0) { return buf; @@ -1729,7 +1755,8 @@ val buf_fash(val buf, val bits) ucnum bytes = b / 8; if (bytes >= len) { - return make_buf(bh->len, zero, bh->len); + val len = unum(bh->len); + return make_buf(len, zero, len); } else { ucnum r = b % 8; unsigned acc = 0; @@ -1753,7 +1780,8 @@ val buf_fash(val buf, val bits) ucnum bytes = (-b) / 8; if (bytes >= len) { - return make_buf(bh->len, zero, bh->len); + val len = unum(bh->len); + return make_buf(len, zero, len); } else { ucnum r = (-b) % 8; unsigned acc = 0; @@ -1783,13 +1811,13 @@ val buf_and(val bufa, val bufb) val self = lit("buf-and"); struct buf *ab = buf_handle(bufa, self); struct buf *bb = buf_handle(bufb, self); - ucnum la = c_unum(ab->len, self); - ucnum lb = c_unum(bb->len, self); + ucnum la = ab->len; + ucnum lb = bb->len; if (la == 0) { - return make_buf(bb->len, zero, bb->len); + return make_buf(unum(bb->len), zero, unum(bb->len)); } else if (lb == 0) { - return make_buf(ab->len, zero, ab->len); + return make_buf(unum(ab->len), zero, unum(ab->len)); } else if (la < lb) { return buf_and(bufb, bufa); } else { @@ -1812,8 +1840,8 @@ val buf_test(val bufa, val bufb) val self = lit("buf-test"); struct buf *ab = buf_handle(bufa, self); struct buf *bb = buf_handle(bufb, self); - ucnum la = c_unum(ab->len, self); - ucnum lb = c_unum(bb->len, self); + ucnum la = ab->len; + ucnum lb = bb->len; if (la == 0 || lb == 0 ) { return nil; @@ -1837,8 +1865,8 @@ val buf_or(val bufa, val bufb) val self = lit("buf-or"); struct buf *ab = buf_handle(bufa, self); struct buf *bb = buf_handle(bufb, self); - ucnum la = c_unum(ab->len, self); - ucnum lb = c_unum(bb->len, self); + ucnum la = ab->len; + ucnum lb = bb->len; if (la == 0) { return bufb; @@ -1866,8 +1894,8 @@ val buf_xor(val bufa, val bufb) val self = lit("buf-xor"); struct buf *ab = buf_handle(bufa, self); struct buf *bb = buf_handle(bufb, self); - ucnum la = c_unum(ab->len, self); - ucnum lb = c_unum(bb->len, self); + ucnum la = ab->len; + ucnum lb = bb->len; if (la == 0) { return bufb; @@ -1894,7 +1922,7 @@ val buf_not(val buf) { val self = lit("buf-not"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self); + ucnum l = b->len; if (l == 0) { return buf; @@ -1915,7 +1943,7 @@ val buf_trunc(val buf, val bits) val self = lit("buf-trunc"); cnum b = c_num(bits, self); struct buf *bh = buf_handle(buf, self); - ucnum l = c_unum(bh->len, self); + ucnum l = bh->len; if (b <= 0) { return make_buf(zero, nil, zero); @@ -1942,7 +1970,7 @@ val buf_bitset(val buf) { val self = lit("buf-bitset"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self), i, j; + ucnum l = b->len, i, j; list_collect_decl (out, ptail); for (i = l - 1, j = 0; i != convert(ucnum, -1); --i, j++) { @@ -1975,7 +2003,7 @@ val buf_bit(val buf, val bit) { val self = lit("buf-bit"); struct buf *bh = buf_handle(buf, self); - ucnum l = c_unum(bh->len, self); + ucnum l = bh->len; cnum b = c_num(bit, self); if (b < 0) { @@ -1995,7 +2023,7 @@ val buf_zero_p(val buf) { val self = lit("buf-zero-p"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self), i; + ucnum l = b->len, i; ucnum *ucdata = coerce(ucnum *, b->data); for (i = 0; i < l / sizeof (ucnum); i++) { @@ -2014,7 +2042,7 @@ val buf_count_ones(val buf) { val self = lit("buf-count-ones"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self), i; + ucnum l = b->len, i; ucnum *ucdata = coerce(ucnum *, b->data); ucnum total[2] = { 0, 0 }; @@ -2079,7 +2107,7 @@ val buf_binary_width(val buf) { val self = lit("buf-bit-width"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self), i; + ucnum l = b->len, i; ucnum *ucdata = coerce(ucnum *, b->data); ucnum zeros[2] = { 0, 0 }; int found = 0; @@ -2167,7 +2195,7 @@ val buf_xor_pattern(val buf, val pat) { val self = lit("buf-xor-pattern"); struct buf *b = buf_handle(buf, self); - ucnum l = c_unum(b->len, self), pl; + ucnum l = b->len, pl; mem_t *p = 0, *fr = 0; unsigned char pbuf[SIZEOF_PTR] = { 0 }; int left = 0; |