1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * queue.c - simple in-process message queuing
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: queue.c,v 1.22 2008/05/15 14:26:30 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <time.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <inttypes.h>
40 #include <sys/types.h>
41
42 #include "spandsp/queue.h"
43
queue_empty(queue_state_t * s)44 int queue_empty(queue_state_t *s)
45 {
46 return (s->iptr == s->optr);
47 }
48 /*- End of function --------------------------------------------------------*/
49
queue_free_space(queue_state_t * s)50 int queue_free_space(queue_state_t *s)
51 {
52 int len;
53
54 if ((len = s->optr - s->iptr - 1) < 0)
55 len += s->len;
56 /*endif*/
57 return len;
58 }
59 /*- End of function --------------------------------------------------------*/
60
queue_contents(queue_state_t * s)61 int queue_contents(queue_state_t *s)
62 {
63 int len;
64
65 if ((len = s->iptr - s->optr) < 0)
66 len += s->len;
67 /*endif*/
68 return len;
69 }
70 /*- End of function --------------------------------------------------------*/
71
queue_flush(queue_state_t * s)72 void queue_flush(queue_state_t *s)
73 {
74 s->optr = s->iptr;
75 }
76 /*- End of function --------------------------------------------------------*/
77
queue_view(queue_state_t * s,uint8_t * buf,int len)78 int queue_view(queue_state_t *s, uint8_t *buf, int len)
79 {
80 int real_len;
81 int to_end;
82 int iptr;
83 int optr;
84
85 /* Snapshot the values (although only iptr should be changeable during this processing) */
86 iptr = s->iptr;
87 optr = s->optr;
88 if ((real_len = iptr - optr) < 0)
89 real_len += s->len;
90 /*endif*/
91 if (real_len < len)
92 {
93 if (s->flags & QUEUE_READ_ATOMIC)
94 return -1;
95 /*endif*/
96 }
97 else
98 {
99 real_len = len;
100 }
101 /*endif*/
102 if (real_len == 0)
103 return 0;
104 /*endif*/
105 to_end = s->len - optr;
106 if (iptr < optr && to_end < real_len)
107 {
108 /* A two step process */
109 if (buf)
110 {
111 memcpy(buf, s->data + optr, to_end);
112 memcpy(buf + to_end, s->data, real_len - to_end);
113 }
114 /*endif*/
115 }
116 else
117 {
118 /* A one step process */
119 if (buf)
120 memcpy(buf, s->data + optr, real_len);
121 /*endif*/
122 }
123 /*endif*/
124 return real_len;
125 }
126 /*- End of function --------------------------------------------------------*/
127
queue_read(queue_state_t * s,uint8_t * buf,int len)128 int queue_read(queue_state_t *s, uint8_t *buf, int len)
129 {
130 int real_len;
131 int to_end;
132 int new_optr;
133 int iptr;
134 int optr;
135
136 /* Snapshot the values (although only iptr should be changeable during this processing) */
137 iptr = s->iptr;
138 optr = s->optr;
139 if ((real_len = iptr - optr) < 0)
140 real_len += s->len;
141 /*endif*/
142 if (real_len < len)
143 {
144 if (s->flags & QUEUE_READ_ATOMIC)
145 return -1;
146 /*endif*/
147 }
148 else
149 {
150 real_len = len;
151 }
152 /*endif*/
153 if (real_len == 0)
154 return 0;
155 /*endif*/
156 to_end = s->len - optr;
157 if (iptr < optr && to_end < real_len)
158 {
159 /* A two step process */
160 if (buf)
161 {
162 memcpy(buf, s->data + optr, to_end);
163 memcpy(buf + to_end, s->data, real_len - to_end);
164 }
165 /*endif*/
166 new_optr = real_len - to_end;
167 }
168 else
169 {
170 /* A one step process */
171 if (buf)
172 memcpy(buf, s->data + optr, real_len);
173 /*endif*/
174 new_optr = optr + real_len;
175 if (new_optr > s->len)
176 new_optr = 0;
177 /*endif*/
178 }
179 /*endif*/
180 /* Only change the pointer now we have really finished */
181 s->optr = new_optr;
182 return real_len;
183 }
184 /*- End of function --------------------------------------------------------*/
185
queue_read_byte(queue_state_t * s)186 int queue_read_byte(queue_state_t *s)
187 {
188 int real_len;
189 int to_end;
190 int iptr;
191 int optr;
192 int byte;
193
194 /* Snapshot the values (although only iptr should be changeable during this processing) */
195 iptr = s->iptr;
196 optr = s->optr;
197 if ((real_len = iptr - optr) < 0)
198 real_len += s->len;
199 /*endif*/
200 if (real_len < 1)
201 return -1;
202 /*endif*/
203 to_end = s->len - optr;
204 byte = s->data[optr];
205 if (++optr >= s->len)
206 optr = 0;
207 /*endif*/
208 /* Only change the pointer now we have really finished */
209 s->optr = optr;
210 return byte;
211 }
212 /*- End of function --------------------------------------------------------*/
213
queue_write(queue_state_t * s,const uint8_t * buf,int len)214 int queue_write(queue_state_t *s, const uint8_t *buf, int len)
215 {
216 int real_len;
217 int to_end;
218 int new_iptr;
219 int iptr;
220 int optr;
221
222 /* Snapshot the values (although only optr should be changeable during this processing) */
223 iptr = s->iptr;
224 optr = s->optr;
225
226 if ((real_len = optr - iptr - 1) < 0)
227 real_len += s->len;
228 /*endif*/
229 if (real_len < len)
230 {
231 if (s->flags & QUEUE_WRITE_ATOMIC)
232 return -1;
233 /*endif*/
234 }
235 else
236 {
237 real_len = len;
238 }
239 /*endif*/
240 if (real_len == 0)
241 return 0;
242 /*endif*/
243 to_end = s->len - iptr;
244 if (iptr < optr || to_end >= real_len)
245 {
246 /* A one step process */
247 memcpy(s->data + iptr, buf, real_len);
248 new_iptr = iptr + real_len;
249 if (new_iptr > s->len)
250 new_iptr = 0;
251 /*endif*/
252 }
253 else
254 {
255 /* A two step process */
256 memcpy(s->data + iptr, buf, to_end);
257 memcpy(s->data, buf + to_end, real_len - to_end);
258 new_iptr = real_len - to_end;
259 }
260 /*endif*/
261 /* Only change the pointer now we have really finished */
262 s->iptr = new_iptr;
263 return real_len;
264 }
265 /*- End of function --------------------------------------------------------*/
266
queue_write_byte(queue_state_t * s,uint8_t byte)267 int queue_write_byte(queue_state_t *s, uint8_t byte)
268 {
269 int real_len;
270 int iptr;
271 int optr;
272
273 /* Snapshot the values (although only optr should be changeable during this processing) */
274 iptr = s->iptr;
275 optr = s->optr;
276
277 if ((real_len = optr - iptr - 1) < 0)
278 real_len += s->len;
279 /*endif*/
280 if (real_len < 1)
281 {
282 if (s->flags & QUEUE_WRITE_ATOMIC)
283 return -1;
284 /*endif*/
285 return 0;
286 }
287 /*endif*/
288 s->data[iptr] = byte;
289 if (++iptr >= s->len)
290 iptr = 0;
291 /*endif*/
292 /* Only change the pointer now we have really finished */
293 s->iptr = iptr;
294 return 1;
295 }
296 /*- End of function --------------------------------------------------------*/
297
queue_state_test_msg(queue_state_t * s)298 int queue_state_test_msg(queue_state_t *s)
299 {
300 uint16_t lenx;
301
302 if (queue_view(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t))
303 return -1;
304 /*endif*/
305 return lenx;
306 }
307 /*- End of function --------------------------------------------------------*/
308
queue_read_msg(queue_state_t * s,uint8_t * buf,int len)309 int queue_read_msg(queue_state_t *s, uint8_t *buf, int len)
310 {
311 uint16_t lenx;
312
313 /* If we assume the write message was atomic, this read message should be
314 safe when conducted in multiple chunks */
315 if (queue_read(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t))
316 return -1;
317 /*endif*/
318 /* If we got this far, the actual message chunk should be guaranteed to be
319 available */
320 if (lenx == 0)
321 return 0;
322 /*endif*/
323 if ((int) lenx > len)
324 {
325 len = queue_read(s, buf, len);
326 /* Discard the rest of the message */
327 queue_read(s, NULL, lenx - len);
328 return len;
329 }
330 /*endif*/
331 return queue_read(s, buf, lenx);
332 }
333 /*- End of function --------------------------------------------------------*/
334
queue_write_msg(queue_state_t * s,const uint8_t * buf,int len)335 int queue_write_msg(queue_state_t *s, const uint8_t *buf, int len)
336 {
337 int real_len;
338 int to_end;
339 int new_iptr;
340 int iptr;
341 int optr;
342 uint16_t lenx;
343
344 /* Snapshot the values (although only optr should be changeable during this processing) */
345 iptr = s->iptr;
346 optr = s->optr;
347
348 if ((real_len = optr - iptr - 1) < 0)
349 real_len += s->len;
350 /*endif*/
351 if (real_len < len + sizeof(uint16_t))
352 return -1;
353 /*endif*/
354 real_len = len + sizeof(uint16_t);
355
356 to_end = s->len - iptr;
357 lenx = (uint16_t) len;
358 if (iptr < optr || to_end >= real_len)
359 {
360 /* A one step process */
361 memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
362 memcpy(s->data + iptr + sizeof(uint16_t), buf, len);
363 new_iptr = iptr + real_len;
364 if (new_iptr > s->len)
365 new_iptr = 0;
366 /*endif*/
367 }
368 else
369 {
370 /* A two step process */
371 if (to_end >= sizeof(uint16_t))
372 {
373 /* The actual message wraps around the end of the buffer */
374 memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
375 memcpy(s->data + iptr + sizeof(uint16_t), buf, to_end - sizeof(uint16_t));
376 memcpy(s->data, buf + to_end - sizeof(uint16_t), real_len - to_end);
377 }
378 else
379 {
380 /* The message length wraps around the end of the buffer */
381 memcpy(s->data + iptr, (uint8_t *) &lenx, to_end);
382 memcpy(s->data, ((uint8_t *) &lenx) + to_end, sizeof(uint16_t) - to_end);
383 memcpy(s->data + sizeof(uint16_t) - to_end, buf, len);
384 }
385 new_iptr = real_len - to_end;
386 }
387 /*endif*/
388 /* Only change the pointer now we have really finished */
389 s->iptr = new_iptr;
390 return len;
391 }
392 /*- End of function --------------------------------------------------------*/
393
queue_init(queue_state_t * s,int len,int flags)394 queue_state_t *queue_init(queue_state_t *s, int len, int flags)
395 {
396 if (s == NULL)
397 {
398 if ((s = (queue_state_t *) malloc(sizeof(*s) + len + 1)) == NULL)
399 return NULL;
400 }
401 s->iptr =
402 s->optr = 0;
403 s->flags = flags;
404 s->len = len + 1;
405 return s;
406 }
407 /*- End of function --------------------------------------------------------*/
408
queue_free(queue_state_t * s)409 int queue_free(queue_state_t *s)
410 {
411 free(s);
412 return 0;
413 }
414 /*- End of function --------------------------------------------------------*/
415 /*- End of file ------------------------------------------------------------*/
416