chan_socketcan_ringbuffer.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "chan_socketcan_ringbuffer.h"
  2. /** * Initializes the ring buffer pointed to by <em>buffer</em>.
  3. * This function can also be used to empty/reset the buffer.
  4. * @param buffer The ring buffer to initialize.
  5. */
  6. void chan_socketcan_ringbuffer_init(chan_socketcan_ringbuffer_t *buffer)
  7. {
  8. buffer->tail_index = 0;
  9. buffer->head_index = 0;
  10. }
  11. /** * Adds a byte to a ring buffer.
  12. * @param buffer The buffer in which the data should be placed.
  13. * @param data The byte to place.
  14. */
  15. void chan_socketcan_ringbuffer_queue(chan_socketcan_ringbuffer_t *buffer, chan_socketcan_ringbuffer_element_t data)
  16. {
  17. /* Is buffer full? */
  18. if (chan_socketcan_ringbuffer_is_full(buffer))
  19. {
  20. /* Is going to overwrite the oldest byte */
  21. /* Increase tail index */
  22. buffer->tail_index = ((buffer->tail_index + 1) & CHAN_SOCKETCAN_RINGBUFFER_MASK);
  23. }
  24. /* Place data in buffer */
  25. buffer->buffer[buffer->head_index] = data;
  26. buffer->head_index = ((buffer->head_index + 1) & CHAN_SOCKETCAN_RINGBUFFER_MASK);
  27. }
  28. /** * Adds an array of bytes to a ring buffer.
  29. * @param buffer The buffer in which the data should be placed.
  30. * @param data A pointer to the array of bytes to place in the queue.
  31. * @param size The size of the array.
  32. */
  33. void chan_socketcan_ringbuffer_queue_arr(chan_socketcan_ringbuffer_t *buffer, const chan_socketcan_ringbuffer_element_t *data, chan_socketcan_ringbuffer_size_t size)
  34. {
  35. /* Add bytes; one by one */
  36. chan_socketcan_ringbuffer_size_t i;
  37. for (i = 0; i < size; i++)
  38. {
  39. chan_socketcan_ringbuffer_queue(buffer, data[i]);
  40. }
  41. }
  42. /** * Returns the oldest byte in a ring buffer.
  43. * @param buffer The buffer from which the data should be returned.
  44. * @param data A pointer to the location at which the data should be placed.
  45. * @return 1 if data was returned; 0 otherwise.
  46. */
  47. chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_dequeue(chan_socketcan_ringbuffer_t *buffer, chan_socketcan_ringbuffer_element_t *data)
  48. {
  49. if (chan_socketcan_ringbuffer_is_empty(buffer))
  50. {
  51. /* No items */
  52. return 0;
  53. }
  54. *data = buffer->buffer[buffer->tail_index];
  55. buffer->tail_index = ((buffer->tail_index + 1) & CHAN_SOCKETCAN_RINGBUFFER_MASK);
  56. return 1;
  57. }
  58. /** * Returns the <em>len</em> oldest bytes in a ring buffer.
  59. * @param buffer The buffer from which the data should be returned.
  60. * @param data A pointer to the array at which the data should be placed.
  61. * @param len The maximum number of bytes to return.
  62. * @return The number of bytes returned.
  63. */
  64. chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_dequeue_arr(chan_socketcan_ringbuffer_t *buffer, chan_socketcan_ringbuffer_element_t *data, chan_socketcan_ringbuffer_size_t len)
  65. {
  66. if (chan_socketcan_ringbuffer_is_empty(buffer))
  67. {
  68. /* No items */
  69. return 0;
  70. }
  71. chan_socketcan_ringbuffer_element_t *data_ptr = data;
  72. chan_socketcan_ringbuffer_size_t cnt = 0;
  73. while ((cnt < len) && chan_socketcan_ringbuffer_dequeue(buffer, data_ptr))
  74. {
  75. cnt++;
  76. data_ptr++;
  77. }
  78. return cnt;
  79. }
  80. /** * Peeks a ring buffer, i.e. returns an element without removing it.
  81. * @param buffer The buffer from which the data should be returned.
  82. * @param data A pointer to the location at which the data should be placed.
  83. * @param index The index to peek. * @return 1 if data was returned; 0 otherwise.
  84. */
  85. chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_peek(chan_socketcan_ringbuffer_t *buffer, chan_socketcan_ringbuffer_element_t *data, chan_socketcan_ringbuffer_size_t index)
  86. {
  87. if (index >= chan_socketcan_ringbuffer_num_items(buffer))
  88. {
  89. /* No items at index */
  90. return 0;
  91. }
  92. /* Add index to pointer */
  93. chan_socketcan_ringbuffer_size_t data_index = ((buffer->tail_index + index) & CHAN_SOCKETCAN_RINGBUFFER_MASK);
  94. *data = buffer->buffer[data_index];
  95. return 1;
  96. }
  97. /** * Returns the number of items in a ring buffer.
  98. * @param buffer The buffer for which the number of items should be returned.
  99. * @return The number of items in the ring buffer.
  100. */
  101. chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_num_items(chan_socketcan_ringbuffer_t *buffer)
  102. {
  103. return ((buffer->head_index - buffer->tail_index) & CHAN_SOCKETCAN_RINGBUFFER_MASK);
  104. }
  105. /** * Returns whether a ring buffer is empty.
  106. * @param buffer The buffer for which it should be returned whether it is empty.
  107. * @return 1 if empty; 0 otherwise.
  108. */
  109. inline chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_is_empty(chan_socketcan_ringbuffer_t *buffer)
  110. {
  111. return (buffer->head_index == buffer->tail_index);
  112. }
  113. /** * Returns whether a ring buffer is full.
  114. * @param buffer The buffer for which it should be returned whether it is full.
  115. * @return 1 if full; 0 otherwise.
  116. */
  117. inline chan_socketcan_ringbuffer_size_t chan_socketcan_ringbuffer_is_full(chan_socketcan_ringbuffer_t *buffer)
  118. {
  119. return ((buffer->head_index - buffer->tail_index) & CHAN_SOCKETCAN_RINGBUFFER_MASK) == CHAN_SOCKETCAN_RINGBUFFER_MASK;
  120. }