1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
2 *
3 * GNU Library General Public License (LGPL) version 2 or later.
4 *
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
7
8 #include <features.h>
9
10 #ifdef __USE_GNU
11 #include "_stdio.h"
12
13
14
15 /* Note: There is a defect in this function. (size_t vs ssize_t). */
16
17 /* glibc function --
18 * Return -1 if error or EOF prior to any chars read.
19 * Return number of chars read (including possible delimiter but not
20 * the terminating nul) otherwise.
21 *
22 * NOTE: If we need to allocate a buffer, we do so prior to attempting
23 * a reading. So space may be allocated even if initially at EOF.
24 */
25
26 #define GETDELIM_GROWBY 64
27
getdelim(char ** __restrict lineptr,size_t * __restrict n,int delimiter,register FILE * __restrict stream)28 ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n,
29 int delimiter, register FILE *__restrict stream)
30 {
31 register char *buf;
32 ssize_t pos = -1;
33 int c;
34 __STDIO_AUTO_THREADLOCK_VAR;
35
36 if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
37 __set_errno(EINVAL); /* though I think we should assert here */
38 } else {
39 __STDIO_AUTO_THREADLOCK(stream);
40
41 if (!(buf = *lineptr)) { /* If passed NULL for buffer, */
42 *n = 0; /* ignore value passed and treat size as 0. */
43 }
44
45 /* Within the loop, pos is actually the current buffer index + 2,
46 * because we want to make sure we have enough space to store
47 * an additional char plus a nul terminator.
48 */
49 pos = 1;
50
51 do {
52 if (pos >= *n) {
53 if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) {
54 pos = -1;
55 break;
56 }
57 *n += GETDELIM_GROWBY;
58 *lineptr = buf;
59 }
60
61 if ((c = __GETC_UNLOCKED(stream)) != EOF) {
62 buf[++pos - 2] = c;
63 if (c != delimiter) {
64 continue;
65 }
66 }
67
68 /* We're done, so correct pos back to being the current index. */
69 if ((pos -= 2) >= 0) {
70 buf[++pos] = 0;
71 }
72 break;
73
74 } while (1);
75
76 __STDIO_AUTO_THREADUNLOCK(stream);
77 }
78
79 return pos;
80 }
81 libc_hidden_def(getdelim)
82 #endif
83