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 ------------------------------------------------------------*/

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