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