diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-11 17:59:21 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-11 19:29:25 +0200 |
commit | c7eae87870da755586446fecb4eb30063c1d641c (patch) | |
tree | 3b8d1a7846bbe356fc1a3700b57582265760bbca /lib/io/src | |
parent | 366ccf20745b23f1eb8554cbe17e6972271de002 (diff) |
libio: move istream buffer logic into interall callbacks
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/io/src')
-rw-r--r-- | lib/io/src/mem.c | 58 | ||||
-rw-r--r-- | lib/io/src/unix/istream.c | 72 | ||||
-rw-r--r-- | lib/io/src/win32/istream.c | 64 | ||||
-rw-r--r-- | lib/io/src/xfrm/istream.c | 64 |
4 files changed, 186 insertions, 72 deletions
diff --git a/lib/io/src/mem.c b/lib/io/src/mem.c index 39e0d6b..bbb186a 100644 --- a/lib/io/src/mem.c +++ b/lib/io/src/mem.c @@ -20,38 +20,52 @@ typedef struct { const void *data; size_t size; + size_t offset; + size_t visible; char *name; } mem_istream_t; -static int mem_in_precache(istream_t *strm) +static int mem_get_buffered_data(istream_t *strm, const sqfs_u8 **out, + size_t *size, size_t want) { mem_istream_t *mem = (mem_istream_t *)strm; - size_t diff; + size_t have = mem->size - mem->offset; - assert(strm->buffer >= mem->buffer); - assert(strm->buffer <= (mem->buffer + mem->bufsz)); - assert(strm->buffer_used <= mem->bufsz); - assert((size_t)(strm->buffer - mem->buffer) <= - (mem->bufsz - strm->buffer_used)); + if (have > mem->bufsz) + have = mem->bufsz; - if (strm->buffer_used > 0) - memmove(mem->buffer, strm->buffer, strm->buffer_used); + if (want > have) + want = have; - strm->buffer = mem->buffer; + if (mem->visible == 0 || mem->visible < want) { + memcpy(mem->buffer + mem->visible, + (const char *)mem->data + mem->offset + mem->visible, + have - mem->visible); + mem->visible = have; + } - diff = mem->bufsz - strm->buffer_used; - if (diff > mem->size) - diff = mem->size; + *out = mem->buffer; + *size = mem->visible; + return (mem->visible == 0) ? 1 : 0; +} - if (diff > 0) { - memcpy(mem->buffer + strm->buffer_used, mem->data, diff); - strm->buffer_used += diff; - mem->data = (const char *)mem->data + diff; - mem->size -= diff; - } +static void mem_advance_buffer(istream_t *strm, size_t count) +{ + mem_istream_t *mem = (mem_istream_t *)strm; - return 0; + assert(count <= mem->visible); + + if (count > 0 && count < mem->visible) + memmove(mem->buffer, mem->buffer + count, mem->visible - count); + + mem->offset += count; + mem->visible -= count; + + if (mem->visible < mem->bufsz) { + memset(mem->buffer + mem->visible, 0, + mem->bufsz - mem->visible); + } } static const char *mem_in_get_filename(istream_t *strm) @@ -88,8 +102,8 @@ istream_t *istream_memory_create(const char *name, size_t bufsz, mem->data = data; mem->size = size; mem->bufsz = bufsz; - strm->buffer = mem->buffer; - strm->precache = mem_in_precache; + strm->get_buffered_data = mem_get_buffered_data; + strm->advance_buffer = mem_advance_buffer; strm->get_filename = mem_in_get_filename; return strm; } diff --git a/lib/io/src/unix/istream.c b/lib/io/src/unix/istream.c index 8a2dc26..60abff1 100644 --- a/lib/io/src/unix/istream.c +++ b/lib/io/src/unix/istream.c @@ -12,30 +12,35 @@ typedef struct { int fd; bool eof; + size_t buffer_offset; + size_t buffer_used; sqfs_u8 buffer[BUFSZ]; } file_istream_t; -static int file_precache(istream_t *strm) +static int precache(istream_t *strm) { file_istream_t *file = (file_istream_t *)strm; - assert(strm->buffer >= file->buffer); - assert(strm->buffer <= (file->buffer + BUFSZ)); - assert(strm->buffer_used <= BUFSZ); - assert((size_t)(strm->buffer - file->buffer) <= - (BUFSZ - strm->buffer_used)); + if (file->eof) + return 0; - if (strm->buffer_used > 0) - memmove(file->buffer, strm->buffer, strm->buffer_used); + if (file->buffer_offset > 0 && + file->buffer_offset < file->buffer_used) { + memmove(file->buffer, file->buffer + file->buffer_offset, + file->buffer_used - file->buffer_offset); + } - strm->buffer = file->buffer; + file->buffer_used -= file->buffer_offset; + file->buffer_offset = 0; - while (!file->eof && strm->buffer_used < BUFSZ) { - ssize_t ret = read(file->fd, file->buffer + strm->buffer_used, - BUFSZ - strm->buffer_used); + while (file->buffer_used < BUFSZ) { + ssize_t ret = read(file->fd, file->buffer + file->buffer_used, + BUFSZ - file->buffer_used); - if (ret == 0) + if (ret == 0) { file->eof = true; + break; + } if (ret < 0) { if (errno == EINTR) @@ -45,12 +50,43 @@ static int file_precache(istream_t *strm) return -1; } - strm->buffer_used += ret; + file->buffer_used += ret; } return 0; } +static int file_get_buffered_data(istream_t *strm, const sqfs_u8 **out, + size_t *size, size_t want) +{ + file_istream_t *file = (file_istream_t *)strm; + + if (want > BUFSZ) + want = BUFSZ; + + if (file->buffer_used == 0 || + (file->buffer_used - file->buffer_offset) < want) { + int ret = precache(strm); + if (ret) + return ret; + } + + *out = file->buffer + file->buffer_offset; + *size = file->buffer_used - file->buffer_offset; + return (file->eof && *size == 0) ? 1 : 0; +} + +static void file_advance_buffer(istream_t *strm, size_t count) +{ + file_istream_t *file = (file_istream_t *)strm; + + assert(count <= file->buffer_used); + + file->buffer_offset += count; + + assert(file->buffer_offset <= file->buffer_used); +} + static const char *file_get_filename(istream_t *strm) { file_istream_t *file = (file_istream_t *)strm; @@ -93,8 +129,8 @@ istream_t *istream_open_file(const char *path) goto fail_path; } - strm->buffer = file->buffer; - strm->precache = file_precache; + strm->get_buffered_data = file_get_buffered_data; + strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; return strm; fail_path: @@ -119,8 +155,8 @@ istream_t *istream_open_stdin(void) goto fail; file->fd = STDIN_FILENO; - strm->buffer = file->buffer; - strm->precache = file_precache; + strm->get_buffered_data = file_get_buffered_data; + strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; return strm; fail: diff --git a/lib/io/src/win32/istream.c b/lib/io/src/win32/istream.c index c4d7458..9bc32a0 100644 --- a/lib/io/src/win32/istream.c +++ b/lib/io/src/win32/istream.c @@ -15,10 +15,12 @@ typedef struct { HANDLE hnd; bool eof; + size_t buffer_offset; + size_t buffer_used; sqfs_u8 buffer[BUFSZ]; } file_istream_t; -static int file_precache(istream_t *strm) +static int precache(istream_t *strm) { file_istream_t *file = (file_istream_t *)strm; DWORD diff, actual; @@ -27,22 +29,21 @@ static int file_precache(istream_t *strm) if (file->eof) return 0; - assert(strm->buffer >= file->buffer); - assert(strm->buffer <= (file->buffer + BUFSZ)); - assert(strm->buffer_used <= BUFSZ); - assert((size_t)(strm->buffer - file->buffer) <= - (BUFSZ - strm->buffer_used)); + if (file->buffer_offset > 0 && + file->buffer_offset < file->buffer_used) { + memmove(file->buffer, file->buffer + file->buffer_offset, + file->buffer_used - file->buffer_offset); + } - if (strm->buffer_used > 0) - memmove(file->buffer, strm->buffer, strm->buffer_used); + file->buffer_used -= file->buffer_offset; + file->buffer_offset = 0; - strm->buffer = file->buffer; hnd = file->path == NULL ? GetStdHandle(STD_INPUT_HANDLE) : file->hnd; - while (strm->buffer_used < sizeof(file->buffer)) { - diff = sizeof(file->buffer) - strm->buffer_used; + while (file->buffer_used < sizeof(file->buffer)) { + diff = sizeof(file->buffer) - file->buffer_used; - if (!ReadFile(hnd, file->buffer + strm->buffer_used, + if (!ReadFile(hnd, file->buffer + file->buffer_used, diff, &actual, NULL)) { DWORD error = GetLastError(); @@ -63,12 +64,43 @@ static int file_precache(istream_t *strm) break; } - strm->buffer_used += actual; + file->buffer_used += actual; } return 0; } +static int file_get_buffered_data(istream_t *strm, const sqfs_u8 **out, + size_t *size, size_t want) +{ + file_istream_t *file = (file_istream_t *)strm; + + if (want > BUFSZ) + want = BUFSZ; + + if (file->buffer_used == 0 || + (file->buffer_used - file->buffer_offset) < want) { + int ret = precache(strm); + if (ret) + return ret; + } + + *out = file->buffer + file->buffer_offset; + *size = file->buffer_used - file->buffer_offset; + return (file->eof && *size == 0) ? 1 : 0; +} + +static void file_advance_buffer(istream_t *strm, size_t count) +{ + file_istream_t *file = (file_istream_t *)strm; + + assert(count <= file->buffer_used); + + file->buffer_offset += count; + + assert(file->buffer_offset <= file->buffer_used); +} + static const char *file_get_filename(istream_t *strm) { file_istream_t *file = (file_istream_t *)strm; @@ -122,7 +154,8 @@ istream_t *istream_open_file(const char *path) free(wpath); strm->buffer = file->buffer; - strm->precache = file_precache; + strm->get_buffered_data = file_get_buffered_data; + strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; return strm; fail_path: @@ -146,7 +179,8 @@ istream_t *istream_open_stdin(void) sqfs_object_init(file, file_destroy, NULL); strm->buffer = file->buffer; - strm->precache = file_precache; + strm->get_buffered_data = file_get_buffered_data; + strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; return strm; } diff --git a/lib/io/src/xfrm/istream.c b/lib/io/src/xfrm/istream.c index bad3e22..c9bc41a 100644 --- a/lib/io/src/xfrm/istream.c +++ b/lib/io/src/xfrm/istream.c @@ -12,27 +12,28 @@ typedef struct istream_xfrm_t { istream_t *wrapped; xfrm_stream_t *xfrm; + size_t buffer_offset; + size_t buffer_used; sqfs_u8 uncompressed[BUFSZ]; } istream_xfrm_t; -static int xfrm_precache(istream_t *base) +static int precache(istream_t *base) { istream_xfrm_t *xfrm = (istream_xfrm_t *)base; int ret; - assert(base->buffer >= xfrm->uncompressed); - assert(base->buffer <= (xfrm->uncompressed + BUFSZ)); - assert(base->buffer_used <= BUFSZ); - assert((size_t)(base->buffer - xfrm->uncompressed) <= - (BUFSZ - base->buffer_used)); - - if (base->buffer_used > 0) - memmove(xfrm->uncompressed, base->buffer, base->buffer_used); + if (xfrm->buffer_offset > 0 && + xfrm->buffer_offset < xfrm->buffer_used) { + memmove(xfrm->uncompressed, + xfrm->uncompressed + xfrm->buffer_offset, + xfrm->buffer_used - xfrm->buffer_offset); + } - base->buffer = xfrm->uncompressed; + xfrm->buffer_used -= xfrm->buffer_offset; + xfrm->buffer_offset = 0; for (;;) { - sqfs_u32 in_off = 0, out_off = base->buffer_used; + sqfs_u32 in_off = 0, out_off = xfrm->buffer_used; int mode = XFRM_STREAM_FLUSH_NONE; const sqfs_u8 *ptr; size_t avail; @@ -41,10 +42,8 @@ static int xfrm_precache(istream_t *base) sizeof(xfrm->uncompressed)); if (ret < 0) return ret; - if (ret > 0) { + if (ret > 0) mode = XFRM_STREAM_FLUSH_FULL; - avail = 0; - } ret = xfrm->xfrm->process_data(xfrm->xfrm, ptr, avail, @@ -58,7 +57,7 @@ static int xfrm_precache(istream_t *base) return -1; } - base->buffer_used = out_off; + xfrm->buffer_used = out_off; istream_advance_buffer(xfrm->wrapped, in_off); if (ret == XFRM_STREAM_BUFFER_FULL || out_off >= BUFSZ) @@ -71,6 +70,37 @@ static int xfrm_precache(istream_t *base) return 0; } +static int xfrm_get_buffered_data(istream_t *strm, const sqfs_u8 **out, + size_t *size, size_t want) +{ + istream_xfrm_t *xfrm = (istream_xfrm_t *)strm; + + if (want > BUFSZ) + want = BUFSZ; + + if (xfrm->buffer_used == 0 || + (xfrm->buffer_used - xfrm->buffer_offset) < want) { + int ret = precache(strm); + if (ret) + return ret; + } + + *out = xfrm->uncompressed + xfrm->buffer_offset; + *size = xfrm->buffer_used - xfrm->buffer_offset; + return (*size == 0) ? 1 : 0; +} + +static void xfrm_advance_buffer(istream_t *strm, size_t count) +{ + istream_xfrm_t *xfrm = (istream_xfrm_t *)strm; + + assert(count <= xfrm->buffer_used); + + xfrm->buffer_offset += count; + + assert(xfrm->buffer_offset <= xfrm->buffer_used); +} + static const char *xfrm_get_filename(istream_t *strm) { istream_xfrm_t *xfrm = (istream_xfrm_t *)strm; @@ -100,9 +130,9 @@ istream_t *istream_xfrm_create(istream_t *strm, xfrm_stream_t *xfrm) stream->wrapped = sqfs_grab(strm); stream->xfrm = sqfs_grab(xfrm); - base->precache = xfrm_precache; + base->get_buffered_data = xfrm_get_buffered_data; + base->advance_buffer = xfrm_advance_buffer; base->get_filename = xfrm_get_filename; - base->buffer = stream->uncompressed; return base; fail: fprintf(stderr, "%s: error initializing decompressor stream.\n", |