all repos — mgba @ 7bc605fcc0e04ae6f8ce92e21c9f3654c1930635

mGBA Game Boy Advance Emulator

src/util/circle-buffer.c (view raw)

  1/* Copyright (c) 2013-2014 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba-util/circle-buffer.h>
  7
  8#ifndef NDEBUG
  9static int _checkIntegrity(struct CircleBuffer* buffer) {
 10	if ((int8_t*) buffer->writePtr - (int8_t*) buffer->readPtr == (ssize_t) buffer->size) {
 11		return 1;
 12	}
 13	if ((ssize_t) (buffer->capacity - buffer->size) == ((int8_t*) buffer->writePtr - (int8_t*) buffer->readPtr)) {
 14		return 1;
 15	}
 16	if ((ssize_t) (buffer->capacity - buffer->size) == ((int8_t*) buffer->readPtr - (int8_t*) buffer->writePtr)) {
 17		return 1;
 18	}
 19	return 0;
 20}
 21#endif
 22
 23void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity) {
 24	buffer->data = malloc(capacity);
 25	buffer->capacity = capacity;
 26	CircleBufferClear(buffer);
 27}
 28
 29void CircleBufferDeinit(struct CircleBuffer* buffer) {
 30	free(buffer->data);
 31	buffer->data = 0;
 32}
 33
 34size_t CircleBufferSize(const struct CircleBuffer* buffer) {
 35	return buffer->size;
 36}
 37
 38size_t CircleBufferCapacity(const struct CircleBuffer* buffer) {
 39	return buffer->capacity;
 40}
 41
 42void CircleBufferClear(struct CircleBuffer* buffer) {
 43	buffer->size = 0;
 44	buffer->readPtr = buffer->data;
 45	buffer->writePtr = buffer->data;
 46}
 47
 48int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value) {
 49	int8_t* data = buffer->writePtr;
 50	if (buffer->size + sizeof(int8_t) > buffer->capacity) {
 51		return 0;
 52	}
 53	*data = value;
 54	++data;
 55	size_t size = (int8_t*) data - (int8_t*) buffer->data;
 56	if (size < buffer->capacity) {
 57		buffer->writePtr = data;
 58	} else {
 59		buffer->writePtr = buffer->data;
 60	}
 61	buffer->size += sizeof(int8_t);
 62#ifndef NDEBUG
 63	if (!_checkIntegrity(buffer)) {
 64		abort();
 65	}
 66#endif
 67	return 1;
 68}
 69
 70int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value) {
 71	int32_t* data = buffer->writePtr;
 72	if (buffer->size + sizeof(int32_t) > buffer->capacity) {
 73		return 0;
 74	}
 75	if ((intptr_t) data & 0x3) {
 76		int written = 0;
 77		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]);
 78		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]);
 79		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[2]);
 80		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[3]);
 81		return written;
 82	}
 83	*data = value;
 84	++data;
 85	size_t size = (int8_t*) data - (int8_t*) buffer->data;
 86	if (size < buffer->capacity) {
 87		buffer->writePtr = data;
 88	} else {
 89		buffer->writePtr = buffer->data;
 90	}
 91	buffer->size += sizeof(int32_t);
 92#ifndef NDEBUG
 93	if (!_checkIntegrity(buffer)) {
 94		abort();
 95	}
 96#endif
 97	return 4;
 98}
 99
100int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value) {
101	int16_t* data = buffer->writePtr;
102	if (buffer->size + sizeof(int16_t) > buffer->capacity) {
103		return 0;
104	}
105	if ((intptr_t) data & 0x3) {
106		int written = 0;
107		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]);
108		written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]);
109		return written;
110	}
111	*data = value;
112	++data;
113	size_t size = (int8_t*) data - (int8_t*) buffer->data;
114	if (size < buffer->capacity) {
115		buffer->writePtr = data;
116	} else {
117		buffer->writePtr = buffer->data;
118	}
119	buffer->size += sizeof(int16_t);
120#ifndef NDEBUG
121	if (!_checkIntegrity(buffer)) {
122		abort();
123	}
124#endif
125	return 2;
126}
127
128size_t CircleBufferWrite(struct CircleBuffer* buffer, const void* input, size_t length) {
129	int8_t* data = buffer->writePtr;
130	if (buffer->size + length > buffer->capacity) {
131		return 0;
132	}
133	size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data);
134	if (length <= remaining) {
135		memcpy(data, input, length);
136		if (length == remaining) {
137			buffer->writePtr = buffer->data;
138		} else {
139			buffer->writePtr = (int8_t*) data + length;
140		}
141	} else {
142		memcpy(data, input, remaining);
143		memcpy(buffer->data, (const int8_t*) input + remaining, length - remaining);
144		buffer->writePtr = (int8_t*) buffer->data + length - remaining;
145	}
146
147	buffer->size += length;
148#ifndef NDEBUG
149	if (!_checkIntegrity(buffer)) {
150		abort();
151	}
152#endif
153	return length;
154}
155
156int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) {
157	int8_t* data = buffer->readPtr;
158	if (buffer->size < sizeof(int8_t)) {
159		return 0;
160	}
161	*value = *data;
162	++data;
163	size_t size = (int8_t*) data - (int8_t*) buffer->data;
164	if (size < buffer->capacity) {
165		buffer->readPtr = data;
166	} else {
167		buffer->readPtr = buffer->data;
168	}
169	buffer->size -= sizeof(int8_t);
170#ifndef NDEBUG
171	if (!_checkIntegrity(buffer)) {
172		abort();
173	}
174#endif
175	return 1;
176}
177
178int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value) {
179	int16_t* data = buffer->readPtr;
180	if (buffer->size < sizeof(int16_t)) {
181		return 0;
182	}
183	if ((intptr_t) data & 0x3) {
184		int read = 0;
185		read += CircleBufferRead8(buffer, &((int8_t*) value)[0]);
186		read += CircleBufferRead8(buffer, &((int8_t*) value)[1]);
187		return read;
188	}
189	*value = *data;
190	++data;
191	size_t size = (int8_t*) data - (int8_t*) buffer->data;
192	if (size < buffer->capacity) {
193		buffer->readPtr = data;
194	} else {
195		buffer->readPtr = buffer->data;
196	}
197	buffer->size -= sizeof(int16_t);
198#ifndef NDEBUG
199	if (!_checkIntegrity(buffer)) {
200		abort();
201	}
202#endif
203	return 2;
204}
205
206int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) {
207	int32_t* data = buffer->readPtr;
208	if (buffer->size < sizeof(int32_t)) {
209		return 0;
210	}
211	if ((intptr_t) data & 0x3) {
212		int read = 0;
213		read += CircleBufferRead8(buffer, &((int8_t*) value)[0]);
214		read += CircleBufferRead8(buffer, &((int8_t*) value)[1]);
215		read += CircleBufferRead8(buffer, &((int8_t*) value)[2]);
216		read += CircleBufferRead8(buffer, &((int8_t*) value)[3]);
217		return read;
218	}
219	*value = *data;
220	++data;
221	size_t size = (int8_t*) data - (int8_t*) buffer->data;
222	if (size < buffer->capacity) {
223		buffer->readPtr = data;
224	} else {
225		buffer->readPtr = buffer->data;
226	}
227	buffer->size -= sizeof(int32_t);
228#ifndef NDEBUG
229	if (!_checkIntegrity(buffer)) {
230		abort();
231	}
232#endif
233	return 4;
234}
235
236size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length) {
237	int8_t* data = buffer->readPtr;
238	if (buffer->size == 0) {
239		return 0;
240	}
241	if (length > buffer->size) {
242		length = buffer->size;
243	}
244	size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data);
245	if (length <= remaining) {
246		memcpy(output, data, length);
247		if (length == remaining) {
248			buffer->readPtr = buffer->data;
249		} else {
250			buffer->readPtr = (int8_t*) data + length;
251		}
252	} else {
253		memcpy(output, data, remaining);
254		memcpy((int8_t*) output + remaining, buffer->data, length - remaining);
255		buffer->readPtr = (int8_t*) buffer->data + length - remaining;
256	}
257
258	buffer->size -= length;
259#ifndef NDEBUG
260	if (!_checkIntegrity(buffer)) {
261		abort();
262	}
263#endif
264	return length;
265}
266
267size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length) {
268	int8_t* data = buffer->readPtr;
269	if (buffer->size == 0) {
270		return 0;
271	}
272	if (length > buffer->size) {
273		length = buffer->size;
274	}
275	size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data);
276	if (length <= remaining) {
277		memcpy(output, data, length);
278	} else {
279		memcpy(output, data, remaining);
280		memcpy((int8_t*) output + remaining, buffer->data, length - remaining);
281	}
282
283	return length;
284}