/fifo.c

https://bitbucket.org/a84/gs_public/ · C · 130 lines · 103 code · 20 blank · 7 comment · 15 complexity · b872ec87eb93fb119ffaebeb7bdacee6 MD5 · raw file

  1. /*
  2. * circular fifo buffer
  3. *
  4. * Author: Andrey Dyldin <and@cesbo.com>
  5. */
  6. #include <string.h>
  7. #include <malloc.h>
  8. #include "fifo.h"
  9. typedef unsigned char u8_t;
  10. typedef enum {
  11. FIFO_UNIT_READY = 0,
  12. FIFO_UNIT_SET = 1,
  13. FIFO_UNIT_GO = 2
  14. } fifo_unit_status_t;
  15. typedef struct fifo_unit_s {
  16. struct fifo_unit_s *previous;
  17. fifo_unit_status_t status;
  18. u8_t *data;
  19. struct fifo_unit_s *next;
  20. } fifo_unit_t;
  21. typedef struct {
  22. int count;
  23. int size;
  24. fifo_unit_t *write;
  25. fifo_unit_t *read;
  26. fifo_unit_t *data;
  27. } fifo_t;
  28. void *fifo_init(int count, int size) {
  29. size_t unit_size = sizeof(fifo_unit_t) + size;
  30. size_t data_size = count * unit_size;
  31. size_t out_size = sizeof(fifo_t) + data_size;
  32. u8_t *out = (u8_t *)malloc(out_size);
  33. memset(out, 0, out_size);
  34. fifo_t *f = (fifo_t *)out;
  35. f->count = count;
  36. f->size = size;
  37. f->data = (fifo_unit_t *)&out[sizeof(fifo_t)];
  38. f->write = f->data;
  39. f->read = f->data;
  40. // mkfs :)
  41. u8_t *d = (u8_t *)f->data; // data pointer
  42. fifo_unit_t *p = NULL; // previous unit
  43. fifo_unit_t *c = (fifo_unit_t *)d; // current unit
  44. int i;
  45. for(i = 0; i < count; i++) {
  46. c->data = (u8_t *)&d[sizeof(fifo_unit_t)];
  47. d += unit_size;
  48. c->next = (fifo_unit_t *)d;
  49. c->previous = p;
  50. p = c;
  51. c = c->next;
  52. }
  53. // now c is pointer to end of allocated memory
  54. p->next = f->data;
  55. f->data->previous = p;
  56. return out;
  57. }
  58. int fifo_push(void *fifo, void *data) {
  59. fifo_t *f = (fifo_t *)fifo;
  60. u8_t *d = (u8_t *)data;
  61. fifo_unit_t *c = f->write;
  62. if(c->status == FIFO_UNIT_READY) {
  63. f->write = c->next;
  64. c->status = FIFO_UNIT_SET;
  65. memcpy(c->data, d, f->size);
  66. c->status = FIFO_UNIT_GO;
  67. return f->size;
  68. }
  69. return (0 - c->status);
  70. }
  71. int fifo_pop(void *fifo, void *data) {
  72. fifo_t *f = (fifo_t *)fifo;
  73. u8_t *d = (u8_t *)data;
  74. fifo_unit_t *c = f->read;
  75. if(c->status != FIFO_UNIT_GO) return 0;
  76. f->read = c->next;
  77. memcpy(d, c->data, f->size);
  78. c->status = FIFO_UNIT_READY;
  79. return f->size;
  80. }
  81. void fifo_destroy(void *fifo) {
  82. if(fifo) free(fifo);
  83. }
  84. #if 0
  85. #include <stdio.h>
  86. int main() {
  87. void *fifo = fifo_init(40, sizeof(int));
  88. int i;
  89. for(i = 10; i < 61; i++) {
  90. int ret = fifo_push(fifo, (unsigned char *)&i);
  91. if(ret != sizeof(int)) {
  92. printf("fifo_push error: buffer %d:%s\n", ret
  93. , (ret == -2) ? "overflow" : "unknown");
  94. }
  95. if(i == 30) {
  96. int j;
  97. for(j = 0; j < 10; j++) {
  98. int z = -1;
  99. fifo_pop(fifo, (unsigned char *)&z);
  100. printf("pop_1:%d\n", z);
  101. }
  102. }
  103. }
  104. while(fifo_pop(fifo, (unsigned char *)&i) != 0) {
  105. printf("pop_2:%d\n", i);
  106. }
  107. fifo_destroy(fifo);
  108. return 0;
  109. }
  110. #endif // TEST