cbuf.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) 2015-2018 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. *
  20. *
  21. * FIFO circular byte buffer.
  22. */
  23. #ifndef KERN_CBUF_H
  24. #define KERN_CBUF_H
  25. #include <stdbool.h>
  26. #include <stddef.h>
  27. #include <stdint.h>
  28. /*
  29. * Circular buffer descriptor.
  30. *
  31. * The buffer capacity must be a power-of-two. Indexes are absolute values
  32. * which can overflow. Their difference cannot exceed the capacity.
  33. */
  34. struct cbuf
  35. {
  36. uint8_t *buf;
  37. size_t capacity;
  38. size_t start;
  39. size_t end;
  40. };
  41. static inline size_t
  42. cbuf_capacity (const struct cbuf *cbuf)
  43. {
  44. return (cbuf->capacity);
  45. }
  46. static inline size_t
  47. cbuf_start (const struct cbuf *cbuf)
  48. {
  49. return (cbuf->start);
  50. }
  51. static inline size_t
  52. cbuf_end (const struct cbuf *cbuf)
  53. {
  54. return (cbuf->end);
  55. }
  56. static inline size_t
  57. cbuf_size (const struct cbuf *cbuf)
  58. {
  59. return (cbuf->end - cbuf->start);
  60. }
  61. static inline size_t
  62. cbuf_avail_size (const struct cbuf *cbuf)
  63. {
  64. return (cbuf_capacity (cbuf) - cbuf_size (cbuf));
  65. }
  66. static inline void
  67. cbuf_clear (struct cbuf *cbuf)
  68. {
  69. cbuf->start = cbuf->end;
  70. }
  71. static inline bool
  72. cbuf_range_valid (const struct cbuf *cbuf, size_t start, size_t end)
  73. {
  74. return (end - start <= cbuf_size (cbuf) &&
  75. start - cbuf->start <= cbuf_size (cbuf) &&
  76. cbuf->end - end <= cbuf_size (cbuf));;
  77. }
  78. static inline bool
  79. cbuf_index_valid (const struct cbuf *cbuf, size_t index)
  80. {
  81. return (index - cbuf->start <= cbuf_size (cbuf) &&
  82. cbuf->end - index <= cbuf_size (cbuf));
  83. }
  84. /*
  85. * Initialize a circular buffer.
  86. *
  87. * The descriptor is set to use the given buffer for storage. Capacity
  88. * must be a power-of-two.
  89. */
  90. void cbuf_init (struct cbuf *cbuf, void *buf, size_t capacity);
  91. /*
  92. * Push data to a circular buffer.
  93. *
  94. * If the function isn't allowed to erase old data and the circular buffer
  95. * doesn't have enough unused bytes for the new data, EAGAIN is returned.
  96. */
  97. int cbuf_push (struct cbuf *cbuf, const void *buf, size_t size, bool erase);
  98. /*
  99. * Pop data from a circular buffer.
  100. *
  101. * On entry, the sizep argument points to the size of the output buffer.
  102. * On return, it is updated to the number of bytes actually transferred.
  103. *
  104. * If the buffer is empty, EAGAIN is returned, and the size of the output
  105. * buffer is unmodified.
  106. *
  107. * The output buffer may be NULL, in which case this function acts as if
  108. * it wasn't, but without writing output data.
  109. */
  110. int cbuf_pop (struct cbuf *cbuf, void *buf, size_t *sizep);
  111. /*
  112. * Push a byte to a circular buffer.
  113. *
  114. * If the function isn't allowed to erase old data and the circular buffer
  115. * is full, EAGAIN is returned.
  116. */
  117. int cbuf_pushb (struct cbuf *cbuf, uint8_t byte, bool erase);
  118. /*
  119. * Pop a byte from a circular buffer.
  120. *
  121. * If the buffer is empty, EAGAIN is returned.
  122. *
  123. * The output byte pointer may be NULL, in which case this function acts
  124. * as if it wasn't, but without writing output data.
  125. */
  126. int cbuf_popb (struct cbuf *cbuf, void *bytep);
  127. /*
  128. * Write into a circular buffer at a specific location.
  129. *
  130. * If the given index is outside buffer boundaries, EINVAL is returned.
  131. * The given [index, size) range may extend beyond the end of the circular
  132. * buffer.
  133. */
  134. int cbuf_write (struct cbuf *cbuf, size_t index, const void *buf, size_t size);
  135. /*
  136. * Read from a circular buffer at a specific location.
  137. *
  138. * On entry, the sizep argument points to the size of the output buffer.
  139. * On return, it is updated to the number of bytes actually transferred.
  140. *
  141. * If the given index is outside buffer boundaries, EINVAL is returned.
  142. *
  143. * The circular buffer isn't changed by this operation.
  144. *
  145. * The output buffer may be NULL, in which case this function acts as if
  146. * it wasn't, but without writing output data.
  147. */
  148. int cbuf_read (const struct cbuf *cbuf, size_t index, void *buf, size_t *sizep);
  149. /*
  150. * Set the value of the start/end index.
  151. *
  152. * These functions provide low level access to the circular buffer boundaries
  153. * while making sure its size doesn't exceed its capacity.
  154. *
  155. * Users should try and find a higher level way to manipulate the circular
  156. * buffer, and only resort to using these functions if there's no other choice.
  157. */
  158. void cbuf_set_start (struct cbuf *cbuf, size_t start);
  159. void cbuf_set_end (struct cbuf *cbuf, size_t end);
  160. #endif