diff options
Diffstat (limited to 'toxav/ring_buffer.c')
-rw-r--r-- | toxav/ring_buffer.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/toxav/ring_buffer.c b/toxav/ring_buffer.c new file mode 100644 index 00000000..cef3e943 --- /dev/null +++ b/toxav/ring_buffer.c | |||
@@ -0,0 +1,92 @@ | |||
1 | #include "ring_buffer.h" | ||
2 | |||
3 | #include <stdlib.h> | ||
4 | |||
5 | struct RingBuffer { | ||
6 | uint16_t size; /* Max size */ | ||
7 | uint16_t start; | ||
8 | uint16_t end; | ||
9 | void **data; | ||
10 | }; | ||
11 | |||
12 | bool rb_full(const RingBuffer *b) | ||
13 | { | ||
14 | return (b->end + 1) % b->size == b->start; | ||
15 | } | ||
16 | bool rb_empty(const RingBuffer *b) | ||
17 | { | ||
18 | return b->end == b->start; | ||
19 | } | ||
20 | void *rb_write(RingBuffer *b, void *p) | ||
21 | { | ||
22 | void *rc = NULL; | ||
23 | |||
24 | if ((b->end + 1) % b->size == b->start) { /* full */ | ||
25 | rc = b->data[b->start]; | ||
26 | } | ||
27 | |||
28 | b->data[b->end] = p; | ||
29 | b->end = (b->end + 1) % b->size; | ||
30 | |||
31 | if (b->end == b->start) { | ||
32 | b->start = (b->start + 1) % b->size; | ||
33 | } | ||
34 | |||
35 | return rc; | ||
36 | } | ||
37 | bool rb_read(RingBuffer *b, void **p) | ||
38 | { | ||
39 | if (b->end == b->start) { /* Empty */ | ||
40 | *p = NULL; | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | *p = b->data[b->start]; | ||
45 | b->start = (b->start + 1) % b->size; | ||
46 | return true; | ||
47 | } | ||
48 | RingBuffer *rb_new(int size) | ||
49 | { | ||
50 | RingBuffer *buf = calloc(sizeof(RingBuffer), 1); | ||
51 | |||
52 | if (!buf) { | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | buf->size = size + 1; /* include empty elem */ | ||
57 | |||
58 | if (!(buf->data = calloc(buf->size, sizeof(void *)))) { | ||
59 | free(buf); | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | return buf; | ||
64 | } | ||
65 | void rb_kill(RingBuffer *b) | ||
66 | { | ||
67 | if (b) { | ||
68 | free(b->data); | ||
69 | free(b); | ||
70 | } | ||
71 | } | ||
72 | uint16_t rb_size(const RingBuffer *b) | ||
73 | { | ||
74 | if (rb_empty(b)) { | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | return | ||
79 | b->end > b->start ? | ||
80 | b->end - b->start : | ||
81 | (b->size - b->start) + b->end; | ||
82 | } | ||
83 | uint16_t rb_data(const RingBuffer *b, void **dest) | ||
84 | { | ||
85 | uint16_t i = 0; | ||
86 | |||
87 | for (; i < rb_size(b); i++) { | ||
88 | dest[i] = b->data[(b->start + i) % b->size]; | ||
89 | } | ||
90 | |||
91 | return i; | ||
92 | } | ||