From 4e09bca9e34c226b6d7e34b4fa11248405fd988e Mon Sep 17 00:00:00 2001 From: Anton Kling Date: Sun, 22 Oct 2023 19:50:38 +0200 Subject: Move everything into a new repo. --- userland/libc/stdio/open_memstream.c | 108 +++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 userland/libc/stdio/open_memstream.c (limited to 'userland/libc/stdio/open_memstream.c') diff --git a/userland/libc/stdio/open_memstream.c b/userland/libc/stdio/open_memstream.c new file mode 100644 index 0000000..8f359b9 --- /dev/null +++ b/userland/libc/stdio/open_memstream.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +/* +struct __IO_FILE { + size_t (*write)(FILE *, const unsigned char *, size_t); + size_t (*read)(FILE *, unsigned char *, size_t); + int (*seek)(FILE *, long, int); + long offset_in_file; + int buffered_char; + int has_buffered_char; + int fd; + uint8_t is_eof; + uint8_t has_error; + uint64_t file_size; + void *cookie; +}; +*/ + +struct Memstream { + size_t buffer_usage; + char *buffer; +}; + +#define MEMSTREAM_DEF_SIZE 4096 + +size_t memstream_write(FILE *fp, const unsigned char *buf, size_t n) { + struct Memstream *c = fp->cookie; + // FIXME: Do a reallocation + if (c->buffer_usage + n >= fp->file_size) { + n = fp->file_size - c->buffer_usage; + } + + memcpy(c->buffer + fp->offset_in_file, buf, n); + fp->offset_in_file += n; + if (fp->offset_in_file > c->buffer_usage) + c->buffer_usage = fp->offset_in_file; + return n; +} + +size_t memstream_read(FILE *fp, unsigned char *buf, size_t n) { + struct Memstream *c = fp->cookie; + size_t length_left = c->buffer_usage - fp->offset_in_file; + n = min(length_left, n); + memcpy(buf, c->buffer + fp->offset_in_file, n); + fp->offset_in_file += n; + if (0 == n) + fp->is_eof = 1; + return n; +} + +int memstream_seek(FILE *stream, long offset, int whence) { + switch (whence) { + case SEEK_SET: + stream->offset_in_file = offset; + break; + case SEEK_CUR: + stream->offset_in_file += offset; + break; + case SEEK_END: + stream->offset_in_file = stream->file_size + offset; + break; + default: + assert(0); + break; + } + // FIXME: Error checking + return 0; +} + +FILE *open_memstream(char **bufp, size_t *sizep) { + struct Memstream *c = NULL; + FILE *fp = malloc(sizeof(FILE)); + if (!fp) + return NULL; + + fp->offset_in_file = 0; + fp->buffered_char = 0; + fp->has_buffered_char = 0; + fp->seek = memstream_seek; + fp->fd = -1; + fp->is_eof = 0; + fp->has_error = 0; + fp->file_size = MEMSTREAM_DEF_SIZE; + + fp->write = memstream_write; + fp->read = memstream_read; + + c = malloc(sizeof(struct Memstream)); + if (!c) { + goto _exit_memstream_fail; + } + + fp->cookie = (void *)c; + + c->buffer = *bufp = malloc(MEMSTREAM_DEF_SIZE); + if (!bufp) { + goto _exit_memstream_fail; + } + c->buffer_usage = 0; + + return fp; +_exit_memstream_fail: + free(c); + free(fp); + return NULL; +} -- cgit v1.2.3