cstdio.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. #ifdef DFS_USING_POSIX
  15. ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream)
  16. {
  17. char *cur_pos, *new_lineptr;
  18. size_t new_lineptr_len;
  19. int c;
  20. if (lineptr == NULL || n == NULL || stream == NULL)
  21. {
  22. errno = EINVAL;
  23. return -1;
  24. }
  25. if (*lineptr == NULL)
  26. {
  27. *n = 128; /* init len */
  28. if ((*lineptr = (char *)malloc(*n)) == NULL)
  29. {
  30. errno = ENOMEM;
  31. return -1;
  32. }
  33. }
  34. cur_pos = *lineptr;
  35. for (;;)
  36. {
  37. c = getc(stream);
  38. if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
  39. return -1;
  40. if (c == EOF)
  41. break;
  42. if ((*lineptr + *n - cur_pos) < 2)
  43. {
  44. if (LONG_MAX / 2 < *n)
  45. {
  46. #ifdef EOVERFLOW
  47. errno = EOVERFLOW;
  48. #else
  49. errno = ERANGE; /* no EOVERFLOW defined */
  50. #endif
  51. return -1;
  52. }
  53. new_lineptr_len = *n * 2;
  54. if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL)
  55. {
  56. errno = ENOMEM;
  57. return -1;
  58. }
  59. cur_pos = new_lineptr + (cur_pos - *lineptr);
  60. *lineptr = new_lineptr;
  61. *n = new_lineptr_len;
  62. }
  63. *cur_pos++ = (char)c;
  64. if (c == delim)
  65. break;
  66. }
  67. *cur_pos = '\0';
  68. return (ssize_t)(cur_pos - *lineptr);
  69. }
  70. ssize_t getline(char **lineptr, size_t *n, FILE *stream)
  71. {
  72. return getdelim(lineptr, n, '\n', stream);
  73. }
  74. #endif /* DFS_USING_POSIX */