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}