summaryrefslogtreecommitdiffstats
path: root/lib.h
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-30 06:00:40 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-30 06:00:40 -0700
commitb17df7c06379615e4d1d1f912d6e57fb125294d1 (patch)
tree30b0caffb4b784c622214e722b99f3d5133e9405 /lib.h
parentedfe34e241aafe19e6b29840e18ce318a2d22d61 (diff)
downloadtxr-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 'lib.h')
-rw-r--r--lib.h4
1 files changed, 2 insertions, 2 deletions
diff --git a/lib.h b/lib.h
index 70753bb2..29a1a5db 100644
--- a/lib.h
+++ b/lib.h
@@ -360,8 +360,8 @@ struct range {
struct buf {
obj_common;
mem_t *data;
- val len;
- val size;
+ ucnum len;
+ ucnum size;
};
struct tnod {