1 #include "ring-buffer.h"
5 int cur
; /* index of current element, last added etc. */
6 int start
; /* index of first/oldest element */
7 int end
; /* index of reserved/empty slot */
8 size_t size
; /* buffer capacity / number of slots */
9 bool iterating
; /* whether we are in a sequence of prev/next calls */
10 const void *data
[]; /* user supplied buffer content */
13 static int ringbuf_index_prev(RingBuffer
*buf
, int i
) {
14 return (i
-1+buf
->size
) % buf
->size
;
17 static int ringbuf_index_next(RingBuffer
*buf
, int i
) {
18 return (i
+1) % buf
->size
;
21 static bool ringbuf_isfull(RingBuffer
*buf
) {
22 return ringbuf_index_next(buf
, buf
->end
) == buf
->start
;
25 static bool ringbuf_isempty(RingBuffer
*buf
) {
26 return buf
->start
== buf
->end
;
29 static bool ringbuf_isfirst(RingBuffer
*buf
) {
30 return buf
->cur
== buf
->start
;
33 static bool ringbuf_islast(RingBuffer
*buf
) {
34 return ringbuf_index_next(buf
, buf
->cur
) == buf
->end
;
37 const void *ringbuf_prev(RingBuffer
*buf
) {
38 if (ringbuf_isempty(buf
) || (ringbuf_isfirst(buf
) && buf
->iterating
))
41 buf
->cur
= ringbuf_index_prev(buf
, buf
->cur
);
42 buf
->iterating
= true;
43 return buf
->data
[buf
->cur
];
46 const void *ringbuf_next(RingBuffer
*buf
) {
47 if (ringbuf_isempty(buf
) || ringbuf_islast(buf
))
49 buf
->cur
= ringbuf_index_next(buf
, buf
->cur
);
50 buf
->iterating
= true;
51 return buf
->data
[buf
->cur
];
54 void ringbuf_add(RingBuffer
*buf
, const void *value
) {
55 if (ringbuf_isempty(buf
)) {
56 buf
->end
= ringbuf_index_next(buf
, buf
->end
);
57 } else if (!ringbuf_islast(buf
)) {
58 buf
->cur
= ringbuf_index_next(buf
, buf
->cur
);
59 buf
->end
= ringbuf_index_next(buf
, buf
->cur
);
60 } else if (ringbuf_isfull(buf
)) {
61 buf
->start
= ringbuf_index_next(buf
, buf
->start
);
62 buf
->cur
= ringbuf_index_next(buf
, buf
->cur
);
63 buf
->end
= ringbuf_index_next(buf
, buf
->end
);
65 buf
->cur
= ringbuf_index_next(buf
, buf
->cur
);
66 buf
->end
= ringbuf_index_next(buf
, buf
->end
);
68 buf
->data
[buf
->cur
] = value
;
69 buf
->iterating
= false;
72 void ringbuf_invalidate(RingBuffer
*buf
) {
73 buf
->iterating
= false;
76 RingBuffer
*ringbuf_alloc(size_t size
) {
78 if ((buf
= calloc(1, sizeof(*buf
) + (++size
)*sizeof(buf
->data
[0]))))
83 void ringbuf_free(RingBuffer
*buf
) {