Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |
