cstdio.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2014-05-22 ivanrad implement getline
  9. */
  10. #include "posix/stdio.h"
  11. #include <stdlib.h>
  12. #include <limits.h>
  13. #include <sys/errno.h>
  14. ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
  15. {
  16. char *cur_pos, *new_lineptr;
  17. size_t new_lineptr_len;
  18. int c;
  19. if (lineptr == NULL || n == NULL || stream == NULL)
  20. {
  21. errno = EINVAL;
  22. return -1;
  23. }
  24. if (*lineptr == NULL)
  25. {
  26. *n = 128; /* init len */
  27. if ((*lineptr = (char *)malloc(*n)) == NULL)
  28. {
  29. errno = ENOMEM;
  30. return -1;
  31. }
  32. }
  33. cur_pos = *lineptr;
  34. for (;;)
  35. {
  36. c = getc(stream);
  37. if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
  38. return -1;
  39. if (c == EOF)
  40. break;
  41. if ((*lineptr + *n - cur_pos) < 2)
  42. {
  43. if (LONG_MAX / 2 < *n)
  44. {
  45. #ifdef EOVERFLOW
  46. errno = EOVERFLOW;
  47. #else
  48. errno = ERANGE; /* no EOVERFLOW defined */
  49. #endif
  50. return -1;
  51. }
  52. new_lineptr_len = *n * 2;
  53. if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL)
  54. {
  55. errno = ENOMEM;
  56. return -1;
  57. }
  58. cur_pos = new_lineptr + (cur_pos - *lineptr);
  59. *lineptr = new_lineptr;
  60. *n = new_lineptr_len;
  61. }
  62. *cur_pos++ = (char)c;
  63. if (c == delim)
  64. break;
  65. }
  66. *cur_pos = '\0';
  67. return (ssize_t)(cur_pos - *lineptr);
  68. }
  69. ssize_t getline(char **lineptr, size_t *n, FILE *stream)
  70. {
  71. return getdelim(lineptr, n, '\n', stream);
  72. }