Mercurial > hg > audiostuff
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/src/queue.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,425 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * queue.c - simple in-process message queuing + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2004 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: queue.c,v 1.31 2009/04/11 18:11:19 steveu Exp $ + */ + +/*! \file */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <ctype.h> +#include <stdlib.h> +#include <inttypes.h> +#include <sys/types.h> + +#define SPANDSP_FULLY_DEFINE_QUEUE_STATE_T +#include "spandsp/telephony.h" +#include "spandsp/queue.h" + +#include "spandsp/private/queue.h" + +SPAN_DECLARE(int) queue_empty(queue_state_t *s) +{ + return (s->iptr == s->optr); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_free_space(queue_state_t *s) +{ + int len; + + if ((len = s->optr - s->iptr - 1) < 0) + len += s->len; + /*endif*/ + return len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_contents(queue_state_t *s) +{ + int len; + + if ((len = s->iptr - s->optr) < 0) + len += s->len; + /*endif*/ + return len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) queue_flush(queue_state_t *s) +{ + s->optr = s->iptr; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_view(queue_state_t *s, uint8_t *buf, int len) +{ + int real_len; + int to_end; + int iptr; + int optr; + + /* Snapshot the values (although only iptr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + if ((real_len = iptr - optr) < 0) + real_len += s->len; + /*endif*/ + if (real_len < len) + { + if (s->flags & QUEUE_READ_ATOMIC) + return -1; + /*endif*/ + } + else + { + real_len = len; + } + /*endif*/ + if (real_len == 0) + return 0; + /*endif*/ + to_end = s->len - optr; + if (iptr < optr && to_end < real_len) + { + /* A two step process */ + if (buf) + { + memcpy(buf, s->data + optr, to_end); + memcpy(buf + to_end, s->data, real_len - to_end); + } + /*endif*/ + } + else + { + /* A one step process */ + if (buf) + memcpy(buf, s->data + optr, real_len); + /*endif*/ + } + /*endif*/ + return real_len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len) +{ + int real_len; + int to_end; + int new_optr; + int iptr; + int optr; + + /* Snapshot the values (although only iptr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + if ((real_len = iptr - optr) < 0) + real_len += s->len; + /*endif*/ + if (real_len < len) + { + if (s->flags & QUEUE_READ_ATOMIC) + return -1; + /*endif*/ + } + else + { + real_len = len; + } + /*endif*/ + if (real_len == 0) + return 0; + /*endif*/ + to_end = s->len - optr; + if (iptr < optr && to_end < real_len) + { + /* A two step process */ + if (buf) + { + memcpy(buf, s->data + optr, to_end); + memcpy(buf + to_end, s->data, real_len - to_end); + } + /*endif*/ + new_optr = real_len - to_end; + } + else + { + /* A one step process */ + if (buf) + memcpy(buf, s->data + optr, real_len); + /*endif*/ + new_optr = optr + real_len; + if (new_optr >= s->len) + new_optr = 0; + /*endif*/ + } + /*endif*/ + /* Only change the pointer now we have really finished */ + s->optr = new_optr; + return real_len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_read_byte(queue_state_t *s) +{ + int real_len; + int to_end; + int iptr; + int optr; + int byte; + + /* Snapshot the values (although only iptr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + if ((real_len = iptr - optr) < 0) + real_len += s->len; + /*endif*/ + if (real_len < 1) + return -1; + /*endif*/ + to_end = s->len - optr; + byte = s->data[optr]; + if (++optr >= s->len) + optr = 0; + /*endif*/ + /* Only change the pointer now we have really finished */ + s->optr = optr; + return byte; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_write(queue_state_t *s, const uint8_t *buf, int len) +{ + int real_len; + int to_end; + int new_iptr; + int iptr; + int optr; + + /* Snapshot the values (although only optr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + + if ((real_len = optr - iptr - 1) < 0) + real_len += s->len; + /*endif*/ + if (real_len < len) + { + if (s->flags & QUEUE_WRITE_ATOMIC) + return -1; + /*endif*/ + } + else + { + real_len = len; + } + /*endif*/ + if (real_len == 0) + return 0; + /*endif*/ + to_end = s->len - iptr; + if (iptr < optr || to_end >= real_len) + { + /* A one step process */ + memcpy(s->data + iptr, buf, real_len); + new_iptr = iptr + real_len; + if (new_iptr >= s->len) + new_iptr = 0; + /*endif*/ + } + else + { + /* A two step process */ + memcpy(s->data + iptr, buf, to_end); + memcpy(s->data, buf + to_end, real_len - to_end); + new_iptr = real_len - to_end; + } + /*endif*/ + /* Only change the pointer now we have really finished */ + s->iptr = new_iptr; + return real_len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_write_byte(queue_state_t *s, uint8_t byte) +{ + int real_len; + int iptr; + int optr; + + /* Snapshot the values (although only optr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + + if ((real_len = optr - iptr - 1) < 0) + real_len += s->len; + /*endif*/ + if (real_len < 1) + { + if (s->flags & QUEUE_WRITE_ATOMIC) + return -1; + /*endif*/ + return 0; + } + /*endif*/ + s->data[iptr] = byte; + if (++iptr >= s->len) + iptr = 0; + /*endif*/ + /* Only change the pointer now we have really finished */ + s->iptr = iptr; + return 1; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_state_test_msg(queue_state_t *s) +{ + uint16_t lenx; + + if (queue_view(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t)) + return -1; + /*endif*/ + return lenx; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_read_msg(queue_state_t *s, uint8_t *buf, int len) +{ + uint16_t lenx; + + /* If we assume the write message was atomic, this read message should be + safe when conducted in multiple chunks */ + if (queue_read(s, (uint8_t *) &lenx, sizeof(uint16_t)) != sizeof(uint16_t)) + return -1; + /*endif*/ + /* If we got this far, the actual message chunk should be guaranteed to be + available */ + if (lenx == 0) + return 0; + /*endif*/ + if ((int) lenx > len) + { + len = queue_read(s, buf, len); + /* Discard the rest of the message */ + queue_read(s, NULL, lenx - len); + return len; + } + /*endif*/ + return queue_read(s, buf, lenx); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_write_msg(queue_state_t *s, const uint8_t *buf, int len) +{ + int real_len; + int to_end; + int new_iptr; + int iptr; + int optr; + uint16_t lenx; + + /* Snapshot the values (although only optr should be changeable during this processing) */ + iptr = s->iptr; + optr = s->optr; + + if ((real_len = optr - iptr - 1) < 0) + real_len += s->len; + /*endif*/ + if (real_len < len + (int) sizeof(uint16_t)) + return -1; + /*endif*/ + real_len = len + (int) sizeof(uint16_t); + + to_end = s->len - iptr; + lenx = (uint16_t) len; + if (iptr < optr || to_end >= real_len) + { + /* A one step process */ + memcpy(s->data + iptr, &lenx, sizeof(uint16_t)); + memcpy(s->data + iptr + sizeof(uint16_t), buf, len); + new_iptr = iptr + real_len; + if (new_iptr >= s->len) + new_iptr = 0; + /*endif*/ + } + else + { + /* A two step process */ + if (to_end >= sizeof(uint16_t)) + { + /* The actual message wraps around the end of the buffer */ + memcpy(s->data + iptr, &lenx, sizeof(uint16_t)); + memcpy(s->data + iptr + sizeof(uint16_t), buf, to_end - sizeof(uint16_t)); + memcpy(s->data, buf + to_end - sizeof(uint16_t), real_len - to_end); + } + else + { + /* The message length wraps around the end of the buffer */ + memcpy(s->data + iptr, (uint8_t *) &lenx, to_end); + memcpy(s->data, ((uint8_t *) &lenx) + to_end, sizeof(uint16_t) - to_end); + memcpy(s->data + sizeof(uint16_t) - to_end, buf, len); + } + new_iptr = real_len - to_end; + } + /*endif*/ + /* Only change the pointer now we have really finished */ + s->iptr = new_iptr; + return len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(queue_state_t *) queue_init(queue_state_t *s, int len, int flags) +{ + if (s == NULL) + { + if ((s = (queue_state_t *) malloc(sizeof(*s) + len + 1)) == NULL) + return NULL; + } + s->iptr = + s->optr = 0; + s->flags = flags; + s->len = len + 1; + return s; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_release(queue_state_t *s) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) queue_free(queue_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/