getdelim.c 2.0 KB

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