all repos — mgba @ 10fc916425cbd4650bf8c8a56f8c9428bed052d7

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