comparison spandsp-0.0.6pre17/src/queue.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
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.31 2009/04/11 18:11:19 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 #define SPANDSP_FULLY_DEFINE_QUEUE_STATE_T
43 #include "spandsp/telephony.h"
44 #include "spandsp/queue.h"
45
46 #include "spandsp/private/queue.h"
47
48 SPAN_DECLARE(int) queue_empty(queue_state_t *s)
49 {
50 return (s->iptr == s->optr);
51 }
52 /*- End of function --------------------------------------------------------*/
53
54 SPAN_DECLARE(int) queue_free_space(queue_state_t *s)
55 {
56 int len;
57
58 if ((len = s->optr - s->iptr - 1) < 0)
59 len += s->len;
60 /*endif*/
61 return len;
62 }
63 /*- End of function --------------------------------------------------------*/
64
65 SPAN_DECLARE(int) queue_contents(queue_state_t *s)
66 {
67 int len;
68
69 if ((len = s->iptr - s->optr) < 0)
70 len += s->len;
71 /*endif*/
72 return len;
73 }
74 /*- End of function --------------------------------------------------------*/
75
76 SPAN_DECLARE(void) queue_flush(queue_state_t *s)
77 {
78 s->optr = s->iptr;
79 }
80 /*- End of function --------------------------------------------------------*/
81
82 SPAN_DECLARE(int) queue_view(queue_state_t *s, uint8_t *buf, int len)
83 {
84 int real_len;
85 int to_end;
86 int iptr;
87 int optr;
88
89 /* Snapshot the values (although only iptr should be changeable during this processing) */
90 iptr = s->iptr;
91 optr = s->optr;
92 if ((real_len = iptr - optr) < 0)
93 real_len += s->len;
94 /*endif*/
95 if (real_len < len)
96 {
97 if (s->flags & QUEUE_READ_ATOMIC)
98 return -1;
99 /*endif*/
100 }
101 else
102 {
103 real_len = len;
104 }
105 /*endif*/
106 if (real_len == 0)
107 return 0;
108 /*endif*/
109 to_end = s->len - optr;
110 if (iptr < optr && to_end < real_len)
111 {
112 /* A two step process */
113 if (buf)
114 {
115 memcpy(buf, s->data + optr, to_end);
116 memcpy(buf + to_end, s->data, real_len - to_end);
117 }
118 /*endif*/
119 }
120 else
121 {
122 /* A one step process */
123 if (buf)
124 memcpy(buf, s->data + optr, real_len);
125 /*endif*/
126 }
127 /*endif*/
128 return real_len;
129 }
130 /*- End of function --------------------------------------------------------*/
131
132 SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len)
133 {
134 int real_len;
135 int to_end;
136 int new_optr;
137 int iptr;
138 int optr;
139
140 /* Snapshot the values (although only iptr should be changeable during this processing) */
141 iptr = s->iptr;
142 optr = s->optr;
143 if ((real_len = iptr - optr) < 0)
144 real_len += s->len;
145 /*endif*/
146 if (real_len < len)
147 {
148 if (s->flags & QUEUE_READ_ATOMIC)
149 return -1;
150 /*endif*/
151 }
152 else
153 {
154 real_len = len;
155 }
156 /*endif*/
157 if (real_len == 0)
158 return 0;
159 /*endif*/
160 to_end = s->len - optr;
161 if (iptr < optr && to_end < real_len)
162 {
163 /* A two step process */
164 if (buf)
165 {
166 memcpy(buf, s->data + optr, to_end);
167 memcpy(buf + to_end, s->data, real_len - to_end);
168 }
169 /*endif*/
170 new_optr = real_len - to_end;
171 }
172 else
173 {
174 /* A one step process */
175 if (buf)
176 memcpy(buf, s->data + optr, real_len);
177 /*endif*/
178 new_optr = optr + real_len;
179 if (new_optr >= s->len)
180 new_optr = 0;
181 /*endif*/
182 }
183 /*endif*/
184 /* Only change the pointer now we have really finished */
185 s->optr = new_optr;
186 return real_len;
187 }
188 /*- End of function --------------------------------------------------------*/
189
190 SPAN_DECLARE(int) queue_read_byte(queue_state_t *s)
191 {
192 int real_len;
193 int to_end;
194 int iptr;
195 int optr;
196 int byte;
197
198 /* Snapshot the values (although only iptr should be changeable during this processing) */
199 iptr = s->iptr;
200 optr = s->optr;
201 if ((real_len = iptr - optr) < 0)
202 real_len += s->len;
203 /*endif*/
204 if (real_len < 1)
205 return -1;
206 /*endif*/
207 to_end = s->len - optr;
208 byte = s->data[optr];
209 if (++optr >= s->len)
210 optr = 0;
211 /*endif*/
212 /* Only change the pointer now we have really finished */
213 s->optr = optr;
214 return byte;
215 }
216 /*- End of function --------------------------------------------------------*/
217
218 SPAN_DECLARE(int) queue_write(queue_state_t *s, const uint8_t *buf, int len)
219 {
220 int real_len;
221 int to_end;
222 int new_iptr;
223 int iptr;
224 int optr;
225
226 /* Snapshot the values (although only optr should be changeable during this processing) */
227 iptr = s->iptr;
228 optr = s->optr;
229
230 if ((real_len = optr - iptr - 1) < 0)
231 real_len += s->len;
232 /*endif*/
233 if (real_len < len)
234 {
235 if (s->flags & QUEUE_WRITE_ATOMIC)
236 return -1;
237 /*endif*/
238 }
239 else
240 {
241 real_len = len;
242 }
243 /*endif*/
244 if (real_len == 0)
245 return 0;
246 /*endif*/
247 to_end = s->len - iptr;
248 if (iptr < optr || to_end >= real_len)
249 {
250 /* A one step process */
251 memcpy(s->data + iptr, buf, real_len);
252 new_iptr = iptr + real_len;
253 if (new_iptr >= s->len)
254 new_iptr = 0;
255 /*endif*/
256 }
257 else
258 {
259 /* A two step process */
260 memcpy(s->data + iptr, buf, to_end);
261 memcpy(s->data, buf + to_end, real_len - to_end);
262 new_iptr = real_len - to_end;
263 }
264 /*endif*/
265 /* Only change the pointer now we have really finished */
266 s->iptr = new_iptr;
267 return real_len;
268 }
269 /*- End of function --------------------------------------------------------*/
270
271 SPAN_DECLARE(int) queue_write_byte(queue_state_t *s, uint8_t byte)
272 {
273 int real_len;
274 int iptr;
275 int optr;
276
277 /* Snapshot the values (although only optr should be changeable during this processing) */
278 iptr = s->iptr;
279 optr = s->optr;
280
281 if ((real_len = optr - iptr - 1) < 0)
282 real_len += s->len;
283 /*endif*/
284 if (real_len < 1)
285 {
286 if (s->flags & QUEUE_WRITE_ATOMIC)
287 return -1;
288 /*endif*/
289 return 0;
290 }
291 /*endif*/
292 s->data[iptr] = byte;
293 if (++iptr >= s->len)
294 iptr = 0;
295 /*endif*/
296 /* Only change the pointer now we have really finished */
297 s->iptr = iptr;
298 return 1;
299 }
300 /*- End of function --------------------------------------------------------*/
301
302 SPAN_DECLARE(int) queue_state_test_msg(queue_state_t *s)
303 {
304 uint16_t lenx;
305
306 if (queue_view(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t))
307 return -1;
308 /*endif*/
309 return lenx;
310 }
311 /*- End of function --------------------------------------------------------*/
312
313 SPAN_DECLARE(int) queue_read_msg(queue_state_t *s, uint8_t *buf, int len)
314 {
315 uint16_t lenx;
316
317 /* If we assume the write message was atomic, this read message should be
318 safe when conducted in multiple chunks */
319 if (queue_read(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t))
320 return -1;
321 /*endif*/
322 /* If we got this far, the actual message chunk should be guaranteed to be
323 available */
324 if (lenx == 0)
325 return 0;
326 /*endif*/
327 if ((int) lenx > len)
328 {
329 len = queue_read(s, buf, len);
330 /* Discard the rest of the message */
331 queue_read(s, NULL, lenx - len);
332 return len;
333 }
334 /*endif*/
335 return queue_read(s, buf, lenx);
336 }
337 /*- End of function --------------------------------------------------------*/
338
339 SPAN_DECLARE(int) queue_write_msg(queue_state_t *s, const uint8_t *buf, int len)
340 {
341 int real_len;
342 int to_end;
343 int new_iptr;
344 int iptr;
345 int optr;
346 uint16_t lenx;
347
348 /* Snapshot the values (although only optr should be changeable during this processing) */
349 iptr = s->iptr;
350 optr = s->optr;
351
352 if ((real_len = optr - iptr - 1) < 0)
353 real_len += s->len;
354 /*endif*/
355 if (real_len < len + (int) sizeof(uint16_t))
356 return -1;
357 /*endif*/
358 real_len = len + (int) sizeof(uint16_t);
359
360 to_end = s->len - iptr;
361 lenx = (uint16_t) len;
362 if (iptr < optr || to_end >= real_len)
363 {
364 /* A one step process */
365 memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
366 memcpy(s->data + iptr + sizeof(uint16_t), buf, len);
367 new_iptr = iptr + real_len;
368 if (new_iptr >= s->len)
369 new_iptr = 0;
370 /*endif*/
371 }
372 else
373 {
374 /* A two step process */
375 if (to_end >= sizeof(uint16_t))
376 {
377 /* The actual message wraps around the end of the buffer */
378 memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
379 memcpy(s->data + iptr + sizeof(uint16_t), buf, to_end - sizeof(uint16_t));
380 memcpy(s->data, buf + to_end - sizeof(uint16_t), real_len - to_end);
381 }
382 else
383 {
384 /* The message length wraps around the end of the buffer */
385 memcpy(s->data + iptr, (uint8_t *) &lenx, to_end);
386 memcpy(s->data, ((uint8_t *) &lenx) + to_end, sizeof(uint16_t) - to_end);
387 memcpy(s->data + sizeof(uint16_t) - to_end, buf, len);
388 }
389 new_iptr = real_len - to_end;
390 }
391 /*endif*/
392 /* Only change the pointer now we have really finished */
393 s->iptr = new_iptr;
394 return len;
395 }
396 /*- End of function --------------------------------------------------------*/
397
398 SPAN_DECLARE(queue_state_t *) queue_init(queue_state_t *s, int len, int flags)
399 {
400 if (s == NULL)
401 {
402 if ((s = (queue_state_t *) malloc(sizeof(*s) + len + 1)) == NULL)
403 return NULL;
404 }
405 s->iptr =
406 s->optr = 0;
407 s->flags = flags;
408 s->len = len + 1;
409 return s;
410 }
411 /*- End of function --------------------------------------------------------*/
412
413 SPAN_DECLARE(int) queue_release(queue_state_t *s)
414 {
415 return 0;
416 }
417 /*- End of function --------------------------------------------------------*/
418
419 SPAN_DECLARE(int) queue_free(queue_state_t *s)
420 {
421 free(s);
422 return 0;
423 }
424 /*- End of function --------------------------------------------------------*/
425 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.