getdelim.c 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #include "stdio_impl.h"
  2. #include <string.h>
  3. #include <inttypes.h>
  4. #include <errno.h>
  5. #define MIN(a,b) ((a)<(b) ? (a) : (b))
  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->flags |= F_ERR;
  16. FUNLOCK(f);
  17. errno = EINVAL;
  18. return -1;
  19. }
  20. if (!*s) *n=0;
  21. for (;;) {
  22. z = memchr(f->rpos, delim, f->rend - f->rpos);
  23. k = z ? z - f->rpos + 1 : f->rend - f->rpos;
  24. if (i+k+1 >= *n) {
  25. if (k >= SIZE_MAX/2-i) goto oom;
  26. size_t m = i+k+2;
  27. if (!z && m < SIZE_MAX/4) m += m/2;
  28. tmp = realloc(*s, m);
  29. if (!tmp) {
  30. m = i+k+2;
  31. tmp = realloc(*s, m);
  32. if (!tmp) goto oom;
  33. }
  34. *s = tmp;
  35. *n = m;
  36. }
  37. memcpy(*s+i, f->rpos, k);
  38. f->rpos += k;
  39. i += k;
  40. if (z) break;
  41. if ((c = getc_unlocked(f)) == EOF) {
  42. if (!i || !feof(f)) {
  43. FUNLOCK(f);
  44. return -1;
  45. }
  46. break;
  47. }
  48. if (((*s)[i++] = c) == delim) break;
  49. }
  50. (*s)[i] = 0;
  51. FUNLOCK(f);
  52. return i;
  53. oom:
  54. f->flags |= F_ERR;
  55. FUNLOCK(f);
  56. errno = ENOMEM;
  57. return -1;
  58. }
  59. weak_alias(getdelim, __getdelim);