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