all repos — mgba @ eabac4c413c0b83caa4b9a97c6ab6dc3997b4ca0

mGBA Game Boy Advance Emulator

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}