1 /*
2 * Copyright (c) 2007 - 2015 Joseph Gaeddert
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 //
24 // Buffers, defined by macro
25 //
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "liquid.internal.h"
32
BUFFER(_s)33 struct BUFFER(_s) {
34 T * v;
35 unsigned int len; // length of buffer
36 unsigned int N; // number of elements allocated
37 // in memory
38 unsigned int num_elements; // number of elements currently
39 // in the buffer
40
41 unsigned int read_index;
42 unsigned int write_index;
43
44 buffer_type type;
45
46 // mutex/semaphore
47 };
48
BUFFER(_create)49 BUFFER() BUFFER(_create)(buffer_type _type, unsigned int _n)
50 {
51 BUFFER() b = (BUFFER()) malloc(sizeof(struct BUFFER(_s)));
52 b->type = _type;
53 b->len = _n;
54
55 if (b->type == CIRCULAR)
56 b->N = 2*(b->len) - 1;
57 else
58 b->N = b->len;
59
60 b->v = (T*) malloc((b->N)*sizeof(T));
61 b->num_elements = 0;
62 b->read_index = 0;
63 b->write_index = 0;
64
65 return b;
66 }
67
BUFFER(_destroy)68 void BUFFER(_destroy)(BUFFER() _b)
69 {
70 free(_b->v);
71 free(_b);
72 }
73
BUFFER(_print)74 void BUFFER(_print)(BUFFER() _b)
75 {
76 if (_b->type == CIRCULAR)
77 printf("circular ");
78 else
79 printf("static ");
80 printf("buffer [%u elements] :\n", _b->num_elements);
81 unsigned int i;
82 for (i=0; i<_b->num_elements; i++) {
83 printf("%u", i);
84 BUFFER_PRINT_LINE(_b,(_b->read_index+i)%(_b->len))
85 printf("\n");
86 }
87 }
88
BUFFER(_debug_print)89 void BUFFER(_debug_print)(BUFFER() _b)
90 {
91 if (_b->type == CIRCULAR)
92 printf("circular ");
93 else
94 printf("static ");
95 printf("buffer [%u elements] :\n", _b->num_elements);
96 unsigned int i;
97 for (i=0; i<_b->len; i++) {
98 // print read index pointer
99 if (i==_b->read_index)
100 printf("<r>");
101
102 // print write index pointer
103 if (i==_b->write_index)
104 printf("<w>");
105
106 // print buffer value
107 BUFFER_PRINT_LINE(_b,i)
108 printf("\n");
109 }
110 printf("----------------------------------\n");
111
112 // print excess buffer memory
113 for (i=_b->len; i<_b->N; i++) {
114 BUFFER_PRINT_LINE(_b,i)
115 printf("\n");
116 }
117 }
118
BUFFER(_clear)119 void BUFFER(_clear)(BUFFER() _b)
120 {
121 _b->read_index = 0;
122 _b->write_index = 0;
123 _b->num_elements = 0;
124 }
125
BUFFER(_zero)126 void BUFFER(_zero)(BUFFER() _b)
127 {
128 _b->read_index = 0;
129 _b->write_index = 0;
130 _b->num_elements = _b->len;
131 memset(_b->v, 0, (_b->num_elements)*sizeof(T));
132 }
133
BUFFER(_read)134 void BUFFER(_read)(BUFFER() _b, T ** _v, unsigned int *_n)
135 {
136 if (_b->type == CIRCULAR)
137 BUFFER(_c_read)(_b, _v, _n);
138 else
139 BUFFER(_s_read)(_b, _v, _n);
140 }
141
BUFFER(_c_read)142 void BUFFER(_c_read)(BUFFER() _b, T ** _v, unsigned int *_n)
143 {
144 //printf("buffer_read() trying to read %u elements (%u available)\n", *_n, _b->num_elements);
145 #if 0
146 if (*_n > _b->num_elements) {
147 printf("error: buffer_read(), cannot read more elements than are available\n");
148 *_v = NULL;
149 *_n = 0;
150 return;
151 } else
152 #endif
153 if (*_n > (_b->len - _b->read_index)) {
154 //
155 BUFFER(_linearize)(_b);
156 }
157 *_v = _b->v + _b->read_index;
158 *_n = _b->num_elements;
159 }
160
BUFFER(_s_read)161 void BUFFER(_s_read)(BUFFER() _b, T ** _v, unsigned int *_n)
162 {
163 //printf("buffer_s_read() reading %u elements\n", _b->num_elements);
164 *_v = _b->v;
165 *_n = _b->num_elements;
166 }
167
BUFFER(_release)168 void BUFFER(_release)(BUFFER() _b, unsigned int _n)
169 {
170 if (_b->type == CIRCULAR)
171 BUFFER(_c_release)(_b, _n);
172 else
173 BUFFER(_s_release)(_b, _n);
174 }
175
176
BUFFER(_c_release)177 void BUFFER(_c_release)(BUFFER() _b, unsigned int _n)
178 {
179 // advance read_index by _n making sure not to step on write_index
180 if (_n > _b->num_elements) {
181 printf("error: buffer_c_release(), cannot release more elements in buffer than exist\n");
182 return;
183 }
184
185 _b->read_index = (_b->read_index + _n) % _b->len;
186 _b->num_elements -= _n;
187 }
188
189
BUFFER(_s_release)190 void BUFFER(_s_release)(BUFFER() _b, unsigned int _n)
191 {
192 BUFFER(_clear)(_b);
193 }
194
BUFFER(_write)195 void BUFFER(_write)(BUFFER() _b, T * _v, unsigned int _n)
196 {
197 if (_b->type == CIRCULAR)
198 BUFFER(_c_write)(_b, _v, _n);
199 else
200 BUFFER(_s_write)(_b, _v, _n);
201 }
202
BUFFER(_c_write)203 void BUFFER(_c_write)(BUFFER() _b, T * _v, unsigned int _n)
204 {
205 //
206 if (_n > (_b->len - _b->num_elements)) {
207 printf("error: buffer_write(), cannot write more elements than are available\n");
208 return;
209 }
210
211 _b->num_elements += _n;
212 // space available at end of buffer
213 unsigned int k = _b->len - _b->write_index;
214 //printf("n : %u, k : %u\n", _n, k);
215
216 // check for condition where we need to wrap around
217 if (_n > k) {
218 memcpy(_b->v + _b->write_index, _v, k*sizeof(T));
219 memcpy(_b->v, &_v[k], (_n-k)*sizeof(T));
220 _b->write_index = _n - k;
221 } else {
222 memcpy(_b->v + _b->write_index, _v, _n*sizeof(T));
223 _b->write_index += _n;
224 }
225 }
226
BUFFER(_s_write)227 void BUFFER(_s_write)(BUFFER() _b, T * _v, unsigned int _n)
228 {
229 if (_n > (_b->len - _b->num_elements)) {
230 printf("error: buffer_s_write(), cannot write more elements than are available\n");
231 return;
232 }
233
234 memcpy(_b->v + _b->num_elements, _v, _n*sizeof(T));
235 _b->num_elements += _n;
236 }
237
238 //void BUFFER(_force_write)(BUFFER() _b, T * _v, unsigned int _n)
239
BUFFER(_push)240 void BUFFER(_push)(BUFFER() _b, T _v)
241 {
242 // push value (force write)
243 if (_b->type == CIRCULAR)
244 BUFFER(_c_push)(_b, _v);
245 else
246 BUFFER(_s_push)(_b, _v);
247 }
248
BUFFER(_c_push)249 void BUFFER(_c_push)(BUFFER() _b, T _v)
250 {
251 _b->v[_b->write_index] = _v;
252 if (_b->num_elements < _b->len) {
253 _b->num_elements++;
254 } else {
255 _b->read_index = (_b->read_index+1) % _b->len;
256 }
257 _b->write_index = (_b->write_index+1) % _b->len;
258 }
259
BUFFER(_s_push)260 void BUFFER(_s_push)(BUFFER() _b, T _v)
261 {
262
263 }
264
BUFFER(_linearize)265 void BUFFER(_linearize)(BUFFER() _b)
266 {
267 // check to see if anything needs to be done
268 if ( (_b->len - _b->read_index) > _b->num_elements)
269 return;
270
271 // perform memory copy
272 memcpy(_b->v + _b->len, _b->v, (_b->write_index)*sizeof(T));
273 }
274
275