github.com/afumu/libc@v0.0.6/musl/src/stdio/getdelim.c (about) 1 #include "stdio_impl.h" 2 #include <string.h> 3 #include <stdlib.h> 4 #include <inttypes.h> 5 #include <errno.h> 6 7 ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f) 8 { 9 char *tmp; 10 unsigned char *z; 11 size_t k; 12 size_t i=0; 13 int c; 14 15 FLOCK(f); 16 17 if (!n || !s) { 18 f->mode |= f->mode-1; 19 f->flags |= F_ERR; 20 FUNLOCK(f); 21 errno = EINVAL; 22 return -1; 23 } 24 25 if (!*s) *n=0; 26 27 for (;;) { 28 if (f->rpos != f->rend) { 29 z = memchr(f->rpos, delim, f->rend - f->rpos); 30 k = z ? z - f->rpos + 1 : f->rend - f->rpos; 31 } else { 32 z = 0; 33 k = 0; 34 } 35 if (i+k >= *n) { 36 size_t m = i+k+2; 37 if (!z && m < SIZE_MAX/4) m += m/2; 38 tmp = realloc(*s, m); 39 if (!tmp) { 40 m = i+k+2; 41 tmp = realloc(*s, m); 42 if (!tmp) { 43 /* Copy as much as fits and ensure no 44 * pushback remains in the FILE buf. */ 45 k = *n-i; 46 memcpy(*s+i, f->rpos, k); 47 f->rpos += k; 48 f->mode |= f->mode-1; 49 f->flags |= F_ERR; 50 FUNLOCK(f); 51 errno = ENOMEM; 52 return -1; 53 } 54 } 55 *s = tmp; 56 *n = m; 57 } 58 memcpy(*s+i, f->rpos, k); 59 f->rpos += k; 60 i += k; 61 if (z) break; 62 if ((c = getc_unlocked(f)) == EOF) { 63 if (!i || !feof(f)) { 64 FUNLOCK(f); 65 return -1; 66 } 67 break; 68 } 69 /* If the byte read by getc won't fit without growing the 70 * output buffer, push it back for next iteration. */ 71 if (i+1 >= *n) *--f->rpos = c; 72 else if (((*s)[i++] = c) == delim) break; 73 } 74 (*s)[i] = 0; 75 76 FUNLOCK(f); 77 78 return i; 79 } 80 81 weak_alias(getdelim, __getdelim);