posix_getline.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /* posix_getline.c
  2. * RT-Thread POSIX
  3. * getdelim(), getline() - read a delimited record from stream, ersatz implementation
  4. * This code is unlicensed -- free and released into the public domain.
  5. * https://man7.org/linux/man-pages/man3/getline.3.html
  6. * Authors:
  7. * https://github.com/ivanrad/getline
  8. * https://github.com/mysterywolf/getline/
  9. *
  10. * Meco Man 2020-09-03 First Version
  11. */
  12. #include <posix_getline.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #include <rtlibc.h>
  16. ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream) {
  17. char *cur_pos, *new_lineptr;
  18. size_t new_lineptr_len;
  19. int c;
  20. if (lineptr == NULL || n == NULL || stream == NULL) {
  21. errno = EINVAL;
  22. return -1;
  23. }
  24. if (*lineptr == NULL) {
  25. *n = 128; /* init len */
  26. if ((*lineptr = (char *)malloc(*n)) == NULL) {
  27. errno = ENOMEM;
  28. return -1;
  29. }
  30. }
  31. cur_pos = *lineptr;
  32. for (;;) {
  33. c = getc(stream);
  34. if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
  35. return -1;
  36. if (c == EOF)
  37. break;
  38. if ((*lineptr + *n - cur_pos) < 2) {
  39. if (SSIZE_MAX / 2 < *n) {
  40. #ifdef EOVERFLOW
  41. errno = EOVERFLOW;
  42. #else
  43. errno = ERANGE; /* no EOVERFLOW defined */
  44. #endif
  45. return -1;
  46. }
  47. new_lineptr_len = *n * 2;
  48. if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL) {
  49. errno = ENOMEM;
  50. return -1;
  51. }
  52. cur_pos = new_lineptr + (cur_pos - *lineptr);
  53. *lineptr = new_lineptr;
  54. *n = new_lineptr_len;
  55. }
  56. *cur_pos++ = (char)c;
  57. if (c == delim)
  58. break;
  59. }
  60. *cur_pos = '\0';
  61. return (ssize_t)(cur_pos - *lineptr);
  62. }
  63. ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
  64. return getdelim(lineptr, n, '\n', stream);
  65. }