Make f, F, t, T motion work when replaying a macro
[vis.git] / ring-buffer.c
blob537fb906308a63c4bb5a1e3fe4f8c93c61b1ce67
1 #include "ring-buffer.h"
2 #include <stdlib.h>
4 struct RingBuffer {
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))
39 return NULL;
40 if (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))
48 return NULL;
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);
64 } else {
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) {
77 RingBuffer *buf;
78 if ((buf = calloc(1, sizeof(*buf) + (++size)*sizeof(buf->data[0]))))
79 buf->size = size;
80 return buf;
83 void ringbuf_free(RingBuffer *buf) {
84 free(buf);