aboutsummaryrefslogtreecommitdiff
path: root/ringbuff.c
blob: 1294b3b45f162565fda37f262b1ce47715c66001 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "util.h"

/* --8<-- ring_type */
typedef int T;

struct ring_buffer {
	size_t head, tail;
	T      array[8]; /* fit for your needs... */
};
/* -->8-- */

/* --8<-- ring_init */
void
ring_init(struct ring_buffer *rb)
{
	rb->head = rb->tail = 0;
}
/* -->8-- */

/* --8<-- ring_push_front */
bool
ring_push_front(struct ring_buffer *rb, T data)
{
	const size_t prev = (rb->tail + NELEM(rb->array) - 1) % NELEM(rb->array);

	if ( prev == rb->head ) {
		return false;
	}

	rb->array[prev] = data;
	rb->tail        = prev;

	return true;
}
/* -->8-- */

/* --8<-- ring_push_back */
bool
ring_push_back(struct ring_buffer *rb, T data)
{
	const size_t next = (rb->head + 1) % NELEM(rb->array);

	if ( next == rb->tail ) {
		return false;
	}

	rb->array[rb->head] = data;
	rb->head            = next;

	return true;
}
/* -->8-- */

/* --8<-- ring_pop_front */
bool
ring_pop_front(struct ring_buffer *rb, T *data)
{
	if ( rb->head == rb->tail ) {
		return false;
	}

	const size_t next = (rb->tail + 1) % NELEM(rb->array);

	*data    = rb->array[rb->tail];
	rb->tail = next;

	return true;
}
/* -->8-- */

/* --8<-- ring_pop_back */
bool
ring_pop_back(struct ring_buffer *rb, T *data)
{
	if ( rb->head == rb->tail ) {
		return false;
	}

	const size_t prev = (rb->head + NELEM(rb->array) - 1) % NELEM(rb->array);

	*data    = rb->array[prev];
	rb->head = prev;

	return true;
}
/* -->8-- */

/* --8<-- ring_put */
bool
ring_put(struct ring_buffer *rb, T data)
{
	return ring_push_back(rb, data);
}
/* -->8-- */

/* --8<-- ring_get */
bool
ring_get(struct ring_buffer *rb, T *data)
{
	return ring_pop_front(rb, data);
}
/* -->8-- */

void
debug_print(const char *msg, struct ring_buffer *rb)
{
	printf("%s: head: %zu, tail: %zu\n", msg, rb->head, rb->tail);
}

int
main(void)
{
#if 0
	struct ring_buffer rb;
	ring_init(&rb);
#else
	struct ring_buffer rb = { .head = 0, .tail = 0 };
#endif

	assert(ring_push_back(&rb, 1) == true); // 1
	assert(ring_push_back(&rb, 2) == true); // 1, 2
	assert(ring_push_back(&rb, 3) == true); // 1, 2, 3
	assert(ring_push_back(&rb, 4) == true); // 1, 2, 3, 4

	debug_print("Stand", &rb);

	assert(ring_push_front(&rb, 0) == true);  // 0, 1, 2, 3, 4
	assert(ring_push_front(&rb, -1) == true); // -1, 0, 1, 2, 3, 4

	debug_print("Stand", &rb);

	T temp;
	assert(ring_pop_back(&rb, &temp) == true);  // -1, 0, 1, 2, 3
	assert(ring_pop_front(&rb, &temp) == true); // 0, 1, 2, 3

	debug_print("Stand", &rb);

	assert(ring_push_back(&rb, 4) == true);   // 0, 1, 2, 3, 4
	assert(ring_push_back(&rb, 5) == true);   // 0, 1, 2, 3, 4, 5
	assert(ring_push_back(&rb, 6) == true);   // 0, 1, 2, 3, 4, 5, 6
	assert(ring_push_back(&rb, 7) == false);  // 0, 1, 2, 3, 4, 5, 6
	assert(ring_push_front(&rb, 7) == false); // 0, 1, 2, 3, 4, 5, 6

	while ( ring_pop_back(&rb, &temp) ) {
		printf("temp: %d\n", temp);
	}

	debug_print("Stand", &rb);

	return EXIT_SUCCESS;
}