src/util/circle-buffer.c (view raw)
1#include "circle-buffer.h"
2
3#ifndef NDEBUG
4static int _checkIntegrity(struct CircleBuffer* buffer) {
5 if ((int8_t*) buffer->writePtr - (int8_t*) buffer->readPtr == (ssize_t) buffer->size) {
6 return 1;
7 }
8 if ((ssize_t) (buffer->capacity - buffer->size) == ((int8_t*) buffer->writePtr - (int8_t*) buffer->readPtr)) {
9 return 1;
10 }
11 if ((ssize_t) (buffer->capacity - buffer->size) == ((int8_t*) buffer->readPtr - (int8_t*) buffer->writePtr)) {
12 return 1;
13 }
14 return 0;
15}
16#endif
17
18void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity) {
19 buffer->data = malloc(capacity);
20 buffer->capacity = capacity;
21 CircleBufferClear(buffer);
22}
23
24void CircleBufferDeinit(struct CircleBuffer* buffer) {
25 free(buffer->data);
26 buffer->data = 0;
27}
28
29size_t CircleBufferSize(const struct CircleBuffer* buffer) {
30 return buffer->size;
31}
32
33size_t CircleBufferCapacity(const struct CircleBuffer* buffer) {
34 return buffer->capacity;
35}
36
37void CircleBufferClear(struct CircleBuffer* buffer) {
38 buffer->size = 0;
39 buffer->readPtr = buffer->data;
40 buffer->writePtr = buffer->data;
41}
42
43int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value) {
44 int8_t* data = buffer->writePtr;
45 if (buffer->size + sizeof(int8_t) > buffer->capacity) {
46 return 0;
47 }
48 *data = value;
49 ++data;
50 size_t size = (int8_t*) data - (int8_t*) buffer->data;
51 if (size < buffer->capacity) {
52 buffer->writePtr = data;
53 } else {
54 buffer->writePtr = buffer->data;
55 }
56 buffer->size += sizeof(int8_t);
57#ifndef NDEBUG
58 if (!_checkIntegrity(buffer)) {
59 abort();
60 }
61#endif
62 return 1;
63}
64
65int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value) {
66 int32_t* data = buffer->writePtr;
67 if (buffer->size + sizeof(int32_t) > buffer->capacity) {
68 return 0;
69 }
70 if ((intptr_t) data & 0x3) {
71 int written = 0;
72 written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]);
73 written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]);
74 written += CircleBufferWrite8(buffer, ((int8_t*) &value)[2]);
75 written += CircleBufferWrite8(buffer, ((int8_t*) &value)[3]);
76 return written;
77 }
78 *data = value;
79 ++data;
80 size_t size = (int8_t*) data - (int8_t*) buffer->data;
81 if (size < buffer->capacity) {
82 buffer->writePtr = data;
83 } else {
84 buffer->writePtr = buffer->data;
85 }
86 buffer->size += sizeof(int32_t);
87#ifndef NDEBUG
88 if (!_checkIntegrity(buffer)) {
89 abort();
90 }
91#endif
92 return 4;
93}
94
95int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) {
96 int8_t* data = buffer->readPtr;
97 if (buffer->size < sizeof(int8_t)) {
98 return 0;
99 }
100 *value = *data;
101 ++data;
102 size_t size = (int8_t*) data - (int8_t*) buffer->data;
103 if (size < buffer->capacity) {
104 buffer->readPtr = data;
105 } else {
106 buffer->readPtr = buffer->data;
107 }
108 buffer->size -= sizeof(int8_t);
109#ifndef NDEBUG
110 if (!_checkIntegrity(buffer)) {
111 abort();
112 }
113#endif
114 return 1;
115}
116
117int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) {
118 int32_t* data = buffer->readPtr;
119 if (buffer->size < sizeof(int32_t)) {
120 return 0;
121 }
122 if ((intptr_t) data & 0x3) {
123 int read = 0;
124 read += CircleBufferRead8(buffer, &((int8_t*) value)[0]);
125 read += CircleBufferRead8(buffer, &((int8_t*) value)[1]);
126 read += CircleBufferRead8(buffer, &((int8_t*) value)[2]);
127 read += CircleBufferRead8(buffer, &((int8_t*) value)[3]);
128 return read;
129 }
130 *value = *data;
131 ++data;
132 size_t size = (int8_t*) data - (int8_t*) buffer->data;
133 if (size < buffer->capacity) {
134 buffer->readPtr = data;
135 } else {
136 buffer->readPtr = buffer->data;
137 }
138 buffer->size -= sizeof(int32_t);
139#ifndef NDEBUG
140 if (!_checkIntegrity(buffer)) {
141 abort();
142 }
143#endif
144 return 4;
145}
146
147size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length) {
148 int8_t* data = buffer->readPtr;
149 if (buffer->size == 0) {
150 return 0;
151 }
152 if (length > buffer->size) {
153 length = buffer->size;
154 }
155 size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data);
156 if (length <= remaining) {
157 memcpy(output, data, length);
158 if (length == remaining) {
159 buffer->readPtr = buffer->data;
160 } else {
161 buffer->readPtr = (int8_t*) data + length;
162 }
163 } else {
164 memcpy(output, data, remaining);
165 memcpy((int8_t*) output + remaining, buffer->data, length - remaining);
166 buffer->readPtr = (int8_t*) buffer->data + length - remaining;
167 }
168
169 buffer->size -= length;
170#ifndef NDEBUG
171 if (!_checkIntegrity(buffer)) {
172 abort();
173 }
174#endif
175 return length;
176}
177
178size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length) {
179 int8_t* data = buffer->readPtr;
180 if (buffer->size == 0) {
181 return 0;
182 }
183 if (length > buffer->size) {
184 length = buffer->size;
185 }
186 size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data);
187 if (length <= remaining) {
188 memcpy(output, data, length);
189 } else {
190 memcpy(output, data, remaining);
191 memcpy((int8_t*) output + remaining, buffer->data, length - remaining);
192 }
193
194 return length;
195}