getdelim.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. #include "_stdio.h"
  8. libc_hidden_proto(getdelim)
  9. libc_hidden_proto(__fgetc_unlocked)
  10. /* Note: There is a defect in this function. (size_t vs ssize_t). */
  11. /* glibc function --
  12. * Return -1 if error or EOF prior to any chars read.
  13. * Return number of chars read (including possible delimiter but not
  14. * the terminating nul) otherwise.
  15. *
  16. * NOTE: If we need to allocate a buffer, we do so prior to attempting
  17. * a reading. So space may be allocated even if initially at EOF.
  18. */
  19. #define GETDELIM_GROWBY 64
  20. ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n,
  21. int delimiter, register FILE *__restrict stream)
  22. {
  23. register char *buf;
  24. ssize_t pos = -1;
  25. int c;
  26. __STDIO_AUTO_THREADLOCK_VAR;
  27. if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
  28. __set_errno(EINVAL); /* though I think we should assert here */
  29. } else {
  30. __STDIO_AUTO_THREADLOCK(stream);
  31. if (!(buf = *lineptr)) { /* If passed NULL for buffer, */
  32. *n = 0; /* ignore value passed and treat size as 0. */
  33. }
  34. /* Within the loop, pos is actually the current buffer index + 2,
  35. * because we want to make sure we have enough space to store
  36. * an additional char plus a nul terminator.
  37. */
  38. pos = 1;
  39. do {
  40. if (pos >= *n) {
  41. if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) {
  42. pos = -1;
  43. break;
  44. }
  45. *n += GETDELIM_GROWBY;
  46. *lineptr = buf;
  47. }
  48. if ((c = __GETC_UNLOCKED(stream)) != EOF) {
  49. buf[++pos - 2] = c;
  50. if (c != delimiter) {
  51. continue;
  52. }
  53. }
  54. /* We're done, so correct pos back to being the current index. */
  55. if ((pos -= 2) >= 0) {
  56. buf[++pos] = 0;
  57. }
  58. break;
  59. } while (1);
  60. __STDIO_AUTO_THREADUNLOCK(stream);
  61. }
  62. return pos;
  63. }
  64. libc_hidden_def(getdelim)