• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "stdio_impl.h"
2 #include <string.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include <errno.h>
6 
getdelim(char ** restrict s,size_t * restrict n,int delim,FILE * restrict f)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);
82