io.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Lightweight buffered reading library.
  4. *
  5. * Copyright 2019 Google LLC.
  6. */
  7. #ifndef __API_IO__
  8. #define __API_IO__
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. struct io {
  12. /* File descriptor being read/ */
  13. int fd;
  14. /* Size of the read buffer. */
  15. unsigned int buf_len;
  16. /* Pointer to storage for buffering read. */
  17. char *buf;
  18. /* End of the storage. */
  19. char *end;
  20. /* Currently accessed data pointer. */
  21. char *data;
  22. /* Set true on when the end of file on read error. */
  23. bool eof;
  24. };
  25. static inline void io__init(struct io *io, int fd,
  26. char *buf, unsigned int buf_len)
  27. {
  28. io->fd = fd;
  29. io->buf_len = buf_len;
  30. io->buf = buf;
  31. io->end = buf;
  32. io->data = buf;
  33. io->eof = false;
  34. }
  35. /* Reads one character from the "io" file with similar semantics to fgetc. */
  36. static inline int io__get_char(struct io *io)
  37. {
  38. char *ptr = io->data;
  39. if (io->eof)
  40. return -1;
  41. if (ptr == io->end) {
  42. ssize_t n = read(io->fd, io->buf, io->buf_len);
  43. if (n <= 0) {
  44. io->eof = true;
  45. return -1;
  46. }
  47. ptr = &io->buf[0];
  48. io->end = &io->buf[n];
  49. }
  50. io->data = ptr + 1;
  51. return *ptr;
  52. }
  53. /* Read a hexadecimal value with no 0x prefix into the out argument hex. If the
  54. * first character isn't hexadecimal returns -2, io->eof returns -1, otherwise
  55. * returns the character after the hexadecimal value which may be -1 for eof.
  56. * If the read value is larger than a u64 the high-order bits will be dropped.
  57. */
  58. static inline int io__get_hex(struct io *io, __u64 *hex)
  59. {
  60. bool first_read = true;
  61. *hex = 0;
  62. while (true) {
  63. int ch = io__get_char(io);
  64. if (ch < 0)
  65. return ch;
  66. if (ch >= '0' && ch <= '9')
  67. *hex = (*hex << 4) | (ch - '0');
  68. else if (ch >= 'a' && ch <= 'f')
  69. *hex = (*hex << 4) | (ch - 'a' + 10);
  70. else if (ch >= 'A' && ch <= 'F')
  71. *hex = (*hex << 4) | (ch - 'A' + 10);
  72. else if (first_read)
  73. return -2;
  74. else
  75. return ch;
  76. first_read = false;
  77. }
  78. }
  79. /* Read a positive decimal value with out argument dec. If the first character
  80. * isn't a decimal returns -2, io->eof returns -1, otherwise returns the
  81. * character after the decimal value which may be -1 for eof. If the read value
  82. * is larger than a u64 the high-order bits will be dropped.
  83. */
  84. static inline int io__get_dec(struct io *io, __u64 *dec)
  85. {
  86. bool first_read = true;
  87. *dec = 0;
  88. while (true) {
  89. int ch = io__get_char(io);
  90. if (ch < 0)
  91. return ch;
  92. if (ch >= '0' && ch <= '9')
  93. *dec = (*dec * 10) + ch - '0';
  94. else if (first_read)
  95. return -2;
  96. else
  97. return ch;
  98. first_read = false;
  99. }
  100. }
  101. #endif /* __API_IO__ */