1
0

getdelim.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #include "stdio_impl.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <inttypes.h>
  5. #include <errno.h>
  6. ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f)
  7. {
  8. char *tmp;
  9. unsigned char *z;
  10. size_t k;
  11. size_t i=0;
  12. int c;
  13. FLOCK(f);
  14. if (!n || !s) {
  15. f->mode |= f->mode-1;
  16. f->flags |= F_ERR;
  17. FUNLOCK(f);
  18. errno = EINVAL;
  19. return -1;
  20. }
  21. if (!*s) *n=0;
  22. for (;;) {
  23. if (f->rpos != f->rend) {
  24. z = memchr(f->rpos, delim, f->rend - f->rpos);
  25. k = z ? z - f->rpos + 1 : f->rend - f->rpos;
  26. } else {
  27. z = 0;
  28. k = 0;
  29. }
  30. if (i+k >= *n) {
  31. size_t m = i+k+2;
  32. if (!z && m < SIZE_MAX/4) m += m/2;
  33. tmp = realloc(*s, m);
  34. if (!tmp) {
  35. m = i+k+2;
  36. tmp = realloc(*s, m);
  37. if (!tmp) {
  38. /* Copy as much as fits and ensure no
  39. * pushback remains in the FILE buf. */
  40. k = *n-i;
  41. memcpy(*s+i, f->rpos, k);
  42. f->rpos += k;
  43. f->mode |= f->mode-1;
  44. f->flags |= F_ERR;
  45. FUNLOCK(f);
  46. errno = ENOMEM;
  47. return -1;
  48. }
  49. }
  50. *s = tmp;
  51. *n = m;
  52. }
  53. memcpy(*s+i, f->rpos, k);
  54. f->rpos += k;
  55. i += k;
  56. if (z) break;
  57. if ((c = getc_unlocked(f)) == EOF) {
  58. if (!i || !feof(f)) {
  59. FUNLOCK(f);
  60. return -1;
  61. }
  62. break;
  63. }
  64. /* If the byte read by getc won't fit without growing the
  65. * output buffer, push it back for next iteration. */
  66. if (i+1 >= *n) *--f->rpos = c;
  67. else if (((*s)[i++] = c) == delim) break;
  68. }
  69. (*s)[i] = 0;
  70. FUNLOCK(f);
  71. return i;
  72. }
  73. weak_alias(getdelim, __getdelim);