1#include "stdio_impl.h"
2#include <string.h>
3#include <inttypes.h>
4#include <errno.h>
5
6#define MIN(a,b) ((a)<(b) ? (a) : (b))
7
8ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f)
9{
10	char *tmp;
11	unsigned char *z;
12	size_t k;
13	size_t i=0;
14	int c;
15
16	FLOCK(f);
17
18	if (!n || !s) {
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		z = memchr(f->rpos, delim, f->rend - f->rpos);
29		k = z ? z - f->rpos + 1 : f->rend - f->rpos;
30		if (i+k+1 >= *n) {
31			if (k >= SIZE_MAX/2-i) goto oom;
32			size_t m = i+k+2;
33			if (!z && m < SIZE_MAX/4) m += m/2;
34			tmp = realloc(*s, m);
35			if (!tmp) {
36				m = i+k+2;
37				tmp = realloc(*s, m);
38				if (!tmp) goto oom;
39			}
40			*s = tmp;
41			*n = m;
42		}
43		memcpy(*s+i, f->rpos, k);
44		f->rpos += k;
45		i += k;
46		if (z) break;
47		if ((c = getc_unlocked(f)) == EOF) {
48			if (!i || !feof(f)) {
49				FUNLOCK(f);
50				return -1;
51			}
52			break;
53		}
54		if (((*s)[i++] = c) == delim) break;
55	}
56	(*s)[i] = 0;
57
58	FUNLOCK(f);
59
60	return i;
61oom:
62	f->flags |= F_ERR;
63	FUNLOCK(f);
64	errno = ENOMEM;
65	return -1;
66}
67
68weak_alias(getdelim, __getdelim);
69