You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
2.4KB

  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include <assert.h>
  5. #include "circular_buffer.h"
  6. // The definition of our circular buffer structure is hidden from the user
  7. struct circular_buf {
  8. void **buffer;
  9. size_t head;
  10. size_t tail;
  11. size_t max; //of the buffer
  12. int full;
  13. };
  14. static void advance_pointer(cbuf_handle_t cbuf)
  15. {
  16. assert(cbuf);
  17. if(cbuf->full)
  18. {
  19. cbuf->tail = (cbuf->tail + 1) % cbuf->max;
  20. }
  21. cbuf->head = (cbuf->head + 1) % cbuf->max;
  22. // We mark full because we will advance tail on the next time around
  23. cbuf->full = (cbuf->head == cbuf->tail);
  24. }
  25. static void retreat_pointer(cbuf_handle_t cbuf)
  26. {
  27. assert(cbuf);
  28. cbuf->full = 0;
  29. cbuf->tail = (cbuf->tail + 1) % cbuf->max;
  30. }
  31. cbuf_handle_t circular_buf_init(size_t size)
  32. {
  33. assert(size);
  34. cbuf_handle_t cbuf = malloc(sizeof(struct circular_buf));
  35. assert(cbuf);
  36. cbuf->buffer = malloc(size * sizeof(void*));
  37. cbuf->max = size;
  38. circular_buf_reset(cbuf);
  39. assert(circular_buf_empty(cbuf));
  40. return cbuf;
  41. }
  42. void circular_buf_free(cbuf_handle_t cbuf)
  43. {
  44. assert(cbuf);
  45. assert(cbuf->buffer);
  46. free(cbuf->buffer);
  47. free(cbuf);
  48. }
  49. void circular_buf_reset(cbuf_handle_t cbuf)
  50. {
  51. assert(cbuf);
  52. cbuf->head = 0;
  53. cbuf->tail = 0;
  54. cbuf->full = 0;
  55. }
  56. size_t circular_buf_size(cbuf_handle_t cbuf)
  57. {
  58. assert(cbuf);
  59. size_t size = cbuf->max;
  60. if(!cbuf->full)
  61. {
  62. if(cbuf->head >= cbuf->tail)
  63. {
  64. size = (cbuf->head - cbuf->tail);
  65. }
  66. else
  67. {
  68. size = (cbuf->max + cbuf->head - cbuf->tail);
  69. }
  70. }
  71. return size;
  72. }
  73. size_t circular_buf_capacity(cbuf_handle_t cbuf)
  74. {
  75. assert(cbuf);
  76. return cbuf->max;
  77. }
  78. void circular_buf_put(cbuf_handle_t cbuf, void *data)
  79. {
  80. assert(cbuf && cbuf->buffer);
  81. cbuf->buffer[cbuf->head] = data;
  82. advance_pointer(cbuf);
  83. }
  84. int circular_buf_put2(cbuf_handle_t cbuf, void *data)
  85. {
  86. int r = -1;
  87. assert(cbuf && cbuf->buffer);
  88. if(!circular_buf_full(cbuf))
  89. {
  90. cbuf->buffer[cbuf->head] = data;
  91. advance_pointer(cbuf);
  92. r = 0;
  93. }
  94. return r;
  95. }
  96. int circular_buf_get(cbuf_handle_t cbuf, void **data, int peek)
  97. {
  98. assert(cbuf && cbuf->buffer);
  99. int r = -1;
  100. if(!circular_buf_empty(cbuf))
  101. {
  102. if (data)
  103. *data = cbuf->buffer[cbuf->tail];
  104. if (!peek)
  105. retreat_pointer(cbuf);
  106. r = 0;
  107. }
  108. return r;
  109. }
  110. int circular_buf_empty(cbuf_handle_t cbuf)
  111. {
  112. assert(cbuf);
  113. return (!cbuf->full && (cbuf->head == cbuf->tail));
  114. }
  115. int circular_buf_full(cbuf_handle_t cbuf)
  116. {
  117. assert(cbuf);
  118. return cbuf->full;
  119. }