lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 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 | |
| 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 |