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}