all repos — mgba @ 4e88cc86d97f670d17533fa0293772264bd8d8d4

mGBA Game Boy Advance Emulator

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

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