remove stale document from malloc src directory
[oweals/musl.git] / src / stdio / getdelim.c
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);