all repos — mgba @ d6a28c8a6e469a6f324740308ba1299186d54301

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