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