1570af302Sopenharmony_ci#include "stdio_impl.h" 2570af302Sopenharmony_ci#include <string.h> 3570af302Sopenharmony_ci#include <stdlib.h> 4570af302Sopenharmony_ci#include <inttypes.h> 5570af302Sopenharmony_ci#include <errno.h> 6570af302Sopenharmony_ci 7570af302Sopenharmony_cissize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f) 8570af302Sopenharmony_ci{ 9570af302Sopenharmony_ci char *tmp; 10570af302Sopenharmony_ci unsigned char *z; 11570af302Sopenharmony_ci size_t k; 12570af302Sopenharmony_ci size_t i=0; 13570af302Sopenharmony_ci int c; 14570af302Sopenharmony_ci 15570af302Sopenharmony_ci FLOCK(f); 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci if (!n || !s) { 18570af302Sopenharmony_ci f->mode |= f->mode-1; 19570af302Sopenharmony_ci f->flags |= F_ERR; 20570af302Sopenharmony_ci FUNLOCK(f); 21570af302Sopenharmony_ci errno = EINVAL; 22570af302Sopenharmony_ci return -1; 23570af302Sopenharmony_ci } 24570af302Sopenharmony_ci 25570af302Sopenharmony_ci if (!*s) *n=0; 26570af302Sopenharmony_ci 27570af302Sopenharmony_ci for (;;) { 28570af302Sopenharmony_ci if (f->rpos != f->rend) { 29570af302Sopenharmony_ci z = memchr(f->rpos, delim, f->rend - f->rpos); 30570af302Sopenharmony_ci k = z ? z - f->rpos + 1 : f->rend - f->rpos; 31570af302Sopenharmony_ci } else { 32570af302Sopenharmony_ci z = 0; 33570af302Sopenharmony_ci k = 0; 34570af302Sopenharmony_ci } 35570af302Sopenharmony_ci if (i+k >= *n) { 36570af302Sopenharmony_ci size_t m = i+k+2; 37570af302Sopenharmony_ci if (!z && m < SIZE_MAX/4) m += m/2; 38570af302Sopenharmony_ci tmp = realloc(*s, m); 39570af302Sopenharmony_ci if (!tmp) { 40570af302Sopenharmony_ci m = i+k+2; 41570af302Sopenharmony_ci tmp = realloc(*s, m); 42570af302Sopenharmony_ci if (!tmp) { 43570af302Sopenharmony_ci /* Copy as much as fits and ensure no 44570af302Sopenharmony_ci * pushback remains in the FILE buf. */ 45570af302Sopenharmony_ci k = *n-i; 46570af302Sopenharmony_ci memcpy(*s+i, f->rpos, k); 47570af302Sopenharmony_ci f->rpos += k; 48570af302Sopenharmony_ci f->mode |= f->mode-1; 49570af302Sopenharmony_ci f->flags |= F_ERR; 50570af302Sopenharmony_ci FUNLOCK(f); 51570af302Sopenharmony_ci errno = ENOMEM; 52570af302Sopenharmony_ci return -1; 53570af302Sopenharmony_ci } 54570af302Sopenharmony_ci } 55570af302Sopenharmony_ci *s = tmp; 56570af302Sopenharmony_ci *n = m; 57570af302Sopenharmony_ci } 58570af302Sopenharmony_ci if (k) { 59570af302Sopenharmony_ci memcpy(*s+i, f->rpos, k); 60570af302Sopenharmony_ci f->rpos += k; 61570af302Sopenharmony_ci i += k; 62570af302Sopenharmony_ci } 63570af302Sopenharmony_ci if (z) break; 64570af302Sopenharmony_ci if ((c = getc_unlocked(f)) == EOF) { 65570af302Sopenharmony_ci if (!i || !feof(f)) { 66570af302Sopenharmony_ci FUNLOCK(f); 67570af302Sopenharmony_ci return -1; 68570af302Sopenharmony_ci } 69570af302Sopenharmony_ci break; 70570af302Sopenharmony_ci } 71570af302Sopenharmony_ci /* If the byte read by getc won't fit without growing the 72570af302Sopenharmony_ci * output buffer, push it back for next iteration. */ 73570af302Sopenharmony_ci if (i+1 >= *n) *--f->rpos = c; 74570af302Sopenharmony_ci else if (((*s)[i++] = c) == delim) break; 75570af302Sopenharmony_ci } 76570af302Sopenharmony_ci (*s)[i] = 0; 77570af302Sopenharmony_ci 78570af302Sopenharmony_ci FUNLOCK(f); 79570af302Sopenharmony_ci 80570af302Sopenharmony_ci return i; 81570af302Sopenharmony_ci} 82570af302Sopenharmony_ci 83570af302Sopenharmony_ciweak_alias(getdelim, __getdelim); 84