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