diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
commit | 8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch) | |
tree | df55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-top-half/musl/src/stdio/getdelim.c | |
parent | Initial commit. (diff) | |
download | wasi-libc-upstream/0.0_git20221206.8b7148f.tar.xz wasi-libc-upstream/0.0_git20221206.8b7148f.zip |
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-top-half/musl/src/stdio/getdelim.c')
-rw-r--r-- | libc-top-half/musl/src/stdio/getdelim.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/stdio/getdelim.c b/libc-top-half/musl/src/stdio/getdelim.c new file mode 100644 index 0000000..df11444 --- /dev/null +++ b/libc-top-half/musl/src/stdio/getdelim.c @@ -0,0 +1,83 @@ +#include "stdio_impl.h" +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> +#include <errno.h> + +ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f) +{ + char *tmp; + unsigned char *z; + size_t k; + size_t i=0; + int c; + + FLOCK(f); + + if (!n || !s) { + f->mode |= f->mode-1; + f->flags |= F_ERR; + FUNLOCK(f); + errno = EINVAL; + return -1; + } + + if (!*s) *n=0; + + for (;;) { + if (f->rpos != f->rend) { + z = memchr(f->rpos, delim, f->rend - f->rpos); + k = z ? z - f->rpos + 1 : f->rend - f->rpos; + } else { + z = 0; + k = 0; + } + if (i+k >= *n) { + size_t m = i+k+2; + if (!z && m < SIZE_MAX/4) m += m/2; + tmp = realloc(*s, m); + if (!tmp) { + m = i+k+2; + tmp = realloc(*s, m); + if (!tmp) { + /* Copy as much as fits and ensure no + * pushback remains in the FILE buf. */ + k = *n-i; + memcpy(*s+i, f->rpos, k); + f->rpos += k; + f->mode |= f->mode-1; + f->flags |= F_ERR; + FUNLOCK(f); + errno = ENOMEM; + return -1; + } + } + *s = tmp; + *n = m; + } + if (k) { + memcpy(*s+i, f->rpos, k); + f->rpos += k; + i += k; + } + if (z) break; + if ((c = getc_unlocked(f)) == EOF) { + if (!i || !feof(f)) { + FUNLOCK(f); + return -1; + } + break; + } + /* If the byte read by getc won't fit without growing the + * output buffer, push it back for next iteration. */ + if (i+1 >= *n) *--f->rpos = c; + else if (((*s)[i++] = c) == delim) break; + } + (*s)[i] = 0; + + FUNLOCK(f); + + return i; +} + +weak_alias(getdelim, __getdelim); |