/*
|
/*
|
* ringq.c -- Ring queue buffering module
|
* ringq.c -- Ring queue buffering module
|
*
|
*
|
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
* Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
|
*
|
*
|
* See the file "license.txt" for usage and redistribution license requirements
|
* See the file "license.txt" for usage and redistribution license requirements
|
*/
|
*/
|
|
|
/******************************** Description *********************************/
|
/******************************** Description *********************************/
|
|
|
/*
|
/*
|
* A ring queue allows maximum utilization of memory for data storage and is
|
* A ring queue allows maximum utilization of memory for data storage and is
|
* ideal for input/output buffering. This module provides a highly effecient
|
* ideal for input/output buffering. This module provides a highly effecient
|
* implementation and a vehicle for dynamic strings.
|
* implementation and a vehicle for dynamic strings.
|
*
|
*
|
* WARNING: This is a public implementation and callers have full access to
|
* WARNING: This is a public implementation and callers have full access to
|
* the queue structure and pointers. Change this module very carefully.
|
* the queue structure and pointers. Change this module very carefully.
|
*
|
*
|
* This module follows the open/close model.
|
* This module follows the open/close model.
|
*
|
*
|
* Operation of a ringq where rq is a pointer to a ringq :
|
* Operation of a ringq where rq is a pointer to a ringq :
|
*
|
*
|
* rq->buflen contains the size of the buffer.
|
* rq->buflen contains the size of the buffer.
|
* rq->buf will point to the start of the buffer.
|
* rq->buf will point to the start of the buffer.
|
* rq->servp will point to the first (un-consumed) data byte.
|
* rq->servp will point to the first (un-consumed) data byte.
|
* rq->endp will point to the next free location to which new data is added
|
* rq->endp will point to the next free location to which new data is added
|
* rq->endbuf will point to one past the end of the buffer.
|
* rq->endbuf will point to one past the end of the buffer.
|
*
|
*
|
* Eg. If the ringq contains the data "abcdef", it might look like :
|
* Eg. If the ringq contains the data "abcdef", it might look like :
|
*
|
*
|
* +-------------------------------------------------------------------+
|
* +-------------------------------------------------------------------+
|
* | | | | | | | | a | b | c | d | e | f | | | | |
|
* | | | | | | | | a | b | c | d | e | f | | | | |
|
* +-------------------------------------------------------------------+
|
* +-------------------------------------------------------------------+
|
* ^ ^ ^ ^
|
* ^ ^ ^ ^
|
* | | | |
|
* | | | |
|
* rq->buf rq->servp rq->endp rq->enduf
|
* rq->buf rq->servp rq->endp rq->enduf
|
*
|
*
|
* The queue is empty when servp == endp. This means that the queue will hold
|
* The queue is empty when servp == endp. This means that the queue will hold
|
* at most rq->buflen -1 bytes. It is the fillers responsibility to ensure
|
* at most rq->buflen -1 bytes. It is the fillers responsibility to ensure
|
* the ringq is never filled such that servp == endp.
|
* the ringq is never filled such that servp == endp.
|
*
|
*
|
* It is the fillers responsibility to "wrap" the endp back to point to
|
* It is the fillers responsibility to "wrap" the endp back to point to
|
* rq->buf when the pointer steps past the end. Correspondingly it is the
|
* rq->buf when the pointer steps past the end. Correspondingly it is the
|
* consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
|
* consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
|
* The ringqPutc and ringqGetc routines will do this automatically.
|
* The ringqPutc and ringqGetc routines will do this automatically.
|
*/
|
*/
|
|
|
/********************************* Includes ***********************************/
|
/********************************* Includes ***********************************/
|
|
|
#if UEMF
|
#if UEMF
|
#include "uemf.h"
|
#include "uemf.h"
|
#else
|
#else
|
#include "basic/basicInternal.h"
|
#include "basic/basicInternal.h"
|
#endif
|
#endif
|
|
|
/*********************************** Defines **********************************/
|
/*********************************** Defines **********************************/
|
/*
|
/*
|
* Faster than a function call
|
* Faster than a function call
|
*/
|
*/
|
|
|
#define RINGQ_LEN(rq) \
|
#define RINGQ_LEN(rq) \
|
((rq->servp > rq->endp) ? \
|
((rq->servp > rq->endp) ? \
|
(rq->buflen + (rq->endp - rq->servp)) : \
|
(rq->buflen + (rq->endp - rq->servp)) : \
|
(rq->endp - rq->servp))
|
(rq->endp - rq->servp))
|
|
|
/***************************** Forward Declarations ***************************/
|
/***************************** Forward Declarations ***************************/
|
|
|
static int ringq_grow(ringq_t *rq);
|
static int ringq_grow(ringq_t *rq);
|
|
|
/*********************************** Code *************************************/
|
/*********************************** Code *************************************/
|
/*
|
/*
|
* Create a new ringq. "increment" is the amount to increase the size of the
|
* Create a new ringq. "increment" is the amount to increase the size of the
|
* ringq should it need to grow to accomodate data being added. "maxsize" is
|
* ringq should it need to grow to accomodate data being added. "maxsize" is
|
* an upper limit (sanity level) beyond which the q must not grow. Set maxsize
|
* an upper limit (sanity level) beyond which the q must not grow. Set maxsize
|
* to -1 to imply no upper limit. The buffer for the ringq is always
|
* to -1 to imply no upper limit. The buffer for the ringq is always
|
* dynamically allocated. Set maxsize
|
* dynamically allocated. Set maxsize
|
*/
|
*/
|
|
|
int ringqOpen(ringq_t *rq, int increment, int maxsize)
|
int ringqOpen(ringq_t *rq, int increment, int maxsize)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(increment >= 0);
|
a_assert(increment >= 0);
|
|
|
if ((rq->buf = balloc(B_L, increment)) == NULL) {
|
if ((rq->buf = balloc(B_L, increment)) == NULL) {
|
return -1;
|
return -1;
|
}
|
}
|
rq->maxsize = maxsize;
|
rq->maxsize = maxsize;
|
rq->buflen = increment;
|
rq->buflen = increment;
|
rq->increment = increment;
|
rq->increment = increment;
|
rq->endbuf = &rq->buf[rq->buflen];
|
rq->endbuf = &rq->buf[rq->buflen];
|
rq->servp = rq->buf;
|
rq->servp = rq->buf;
|
rq->endp = rq->buf;
|
rq->endp = rq->buf;
|
*rq->servp = '\0';
|
*rq->servp = '\0';
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Delete a ringq and free the ringq buffer.
|
* Delete a ringq and free the ringq buffer.
|
*/
|
*/
|
|
|
void ringqClose(ringq_t *rq)
|
void ringqClose(ringq_t *rq)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (rq == NULL) {
|
if (rq == NULL) {
|
return;
|
return;
|
}
|
}
|
|
|
ringqFlush(rq);
|
ringqFlush(rq);
|
bfree(B_L, (char*) rq->buf);
|
bfree(B_L, (char*) rq->buf);
|
rq->buf = NULL;
|
rq->buf = NULL;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Return the length of the ringq. Users must fill the queue to a high
|
* Return the length of the ringq. Users must fill the queue to a high
|
* water mark of at most one less than the queue size.
|
* water mark of at most one less than the queue size.
|
*/
|
*/
|
|
|
int ringqLen(ringq_t *rq)
|
int ringqLen(ringq_t *rq)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (rq->servp > rq->endp) {
|
if (rq->servp > rq->endp) {
|
return rq->buflen + rq->endp - rq->servp;
|
return rq->buflen + rq->endp - rq->servp;
|
}
|
}
|
else {
|
else {
|
return rq->endp - rq->servp;
|
return rq->endp - rq->servp;
|
}
|
}
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Get a byte from the queue
|
* Get a byte from the queue
|
*/
|
*/
|
|
|
int ringqGetc(ringq_t *rq)
|
int ringqGetc(ringq_t *rq)
|
{
|
{
|
char_t c;
|
char_t c;
|
char_t* cp;
|
char_t* cp;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (rq->servp == rq->endp) {
|
if (rq->servp == rq->endp) {
|
return -1;
|
return -1;
|
}
|
}
|
|
|
cp = (char_t*) rq->servp;
|
cp = (char_t*) rq->servp;
|
c = *cp++;
|
c = *cp++;
|
rq->servp = (unsigned char *) cp;
|
rq->servp = (unsigned char *) cp;
|
if (rq->servp >= rq->endbuf) {
|
if (rq->servp >= rq->endbuf) {
|
rq->servp = rq->buf;
|
rq->servp = rq->buf;
|
}
|
}
|
return c;
|
return c;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Add a char to the queue. Note if being used to store wide strings
|
* Add a char to the queue. Note if being used to store wide strings
|
* this does not add a trailing '\0'. Grow the q as required.
|
* this does not add a trailing '\0'. Grow the q as required.
|
*/
|
*/
|
|
|
int ringqPutc(ringq_t *rq, char_t c)
|
int ringqPutc(ringq_t *rq, char_t c)
|
{
|
{
|
char_t* cp;
|
char_t* cp;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
return -1;
|
return -1;
|
}
|
}
|
|
|
cp = (char_t*) rq->endp;
|
cp = (char_t*) rq->endp;
|
*cp++ = (char_t) c;
|
*cp++ = (char_t) c;
|
rq->endp = (unsigned char *) cp;
|
rq->endp = (unsigned char *) cp;
|
if (rq->endp >= rq->endbuf) {
|
if (rq->endp >= rq->endbuf) {
|
rq->endp = rq->buf;
|
rq->endp = rq->buf;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Insert a wide character at the front of the queue
|
* Insert a wide character at the front of the queue
|
*/
|
*/
|
|
|
int ringqInsertc(ringq_t *rq, char_t c)
|
int ringqInsertc(ringq_t *rq, char_t c)
|
{
|
{
|
char_t* cp;
|
char_t* cp;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
|
return -1;
|
return -1;
|
}
|
}
|
if (rq->servp <= rq->buf) {
|
if (rq->servp <= rq->buf) {
|
rq->servp = rq->endbuf;
|
rq->servp = rq->endbuf;
|
}
|
}
|
cp = (char_t*) rq->servp;
|
cp = (char_t*) rq->servp;
|
*--cp = (char_t) c;
|
*--cp = (char_t) c;
|
rq->servp = (unsigned char *) cp;
|
rq->servp = (unsigned char *) cp;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Add a string to the queue. Add a trailing wide null (two nulls)
|
* Add a string to the queue. Add a trailing wide null (two nulls)
|
*/
|
*/
|
|
|
int ringqPutstr(ringq_t *rq, char_t *str)
|
int ringqPutstr(ringq_t *rq, char_t *str)
|
{
|
{
|
int rc;
|
int rc;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(str);
|
a_assert(str);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t));
|
rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t));
|
*((char_t*) rq->endp) = (char_t) '\0';
|
*((char_t*) rq->endp) = (char_t) '\0';
|
return rc;
|
return rc;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
#if UNICODE
|
#if UNICODE
|
/*
|
/*
|
* Get a byte from the queue
|
* Get a byte from the queue
|
*/
|
*/
|
|
|
int ringqGetcA(ringq_t *rq)
|
int ringqGetcA(ringq_t *rq)
|
{
|
{
|
unsigned char c;
|
unsigned char c;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (rq->servp == rq->endp) {
|
if (rq->servp == rq->endp) {
|
return -1;
|
return -1;
|
}
|
}
|
|
|
c = *rq->servp++;
|
c = *rq->servp++;
|
if (rq->servp >= rq->endbuf) {
|
if (rq->servp >= rq->endbuf) {
|
rq->servp = rq->buf;
|
rq->servp = rq->buf;
|
}
|
}
|
return c;
|
return c;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Add a byte to the queue. Note if being used to store strings this does not
|
* Add a byte to the queue. Note if being used to store strings this does not
|
* add a trailing '\0'. Grow the q as required.
|
* add a trailing '\0'. Grow the q as required.
|
*/
|
*/
|
|
|
int ringqPutcA(ringq_t *rq, char c)
|
int ringqPutcA(ringq_t *rq, char c)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
return -1;
|
return -1;
|
}
|
}
|
|
|
*rq->endp++ = (unsigned char) c;
|
*rq->endp++ = (unsigned char) c;
|
if (rq->endp >= rq->endbuf) {
|
if (rq->endp >= rq->endbuf) {
|
rq->endp = rq->buf;
|
rq->endp = rq->buf;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Insert a byte at the front of the queue
|
* Insert a byte at the front of the queue
|
*/
|
*/
|
|
|
int ringqInsertcA(ringq_t *rq, char c)
|
int ringqInsertcA(ringq_t *rq, char c)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
|
return -1;
|
return -1;
|
}
|
}
|
if (rq->servp <= rq->buf) {
|
if (rq->servp <= rq->buf) {
|
rq->servp = rq->endbuf;
|
rq->servp = rq->endbuf;
|
}
|
}
|
*--rq->servp = (unsigned char) c;
|
*--rq->servp = (unsigned char) c;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Add a string to the queue. Add a trailing null (not really in the q).
|
* Add a string to the queue. Add a trailing null (not really in the q).
|
* ie. beyond the last valid byte.
|
* ie. beyond the last valid byte.
|
*/
|
*/
|
|
|
int ringqPutstrA(ringq_t *rq, char *str)
|
int ringqPutstrA(ringq_t *rq, char *str)
|
{
|
{
|
int rc;
|
int rc;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(str);
|
a_assert(str);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str));
|
rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str));
|
rq->endp[0] = '\0';
|
rq->endp[0] = '\0';
|
return rc;
|
return rc;
|
}
|
}
|
|
|
#endif /* UNICODE */
|
#endif /* UNICODE */
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Add a block of data to the ringq. Return the number of bytes added.
|
* Add a block of data to the ringq. Return the number of bytes added.
|
* Grow the q as required.
|
* Grow the q as required.
|
*/
|
*/
|
|
|
int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
|
int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
|
{
|
{
|
int this, bytes_put;
|
int this, bytes_put;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(buf);
|
a_assert(buf);
|
a_assert(0 <= size);
|
a_assert(0 <= size);
|
|
|
/*
|
/*
|
* Loop adding the maximum bytes we can add in a single straight line copy
|
* Loop adding the maximum bytes we can add in a single straight line copy
|
*/
|
*/
|
bytes_put = 0;
|
bytes_put = 0;
|
while (size > 0) {
|
while (size > 0) {
|
this = min(ringqPutBlkMax(rq), size);
|
this = min(ringqPutBlkMax(rq), size);
|
if (this <= 0) {
|
if (this <= 0) {
|
if (! ringq_grow(rq)) {
|
if (! ringq_grow(rq)) {
|
break;
|
break;
|
}
|
}
|
this = min(ringqPutBlkMax(rq), size);
|
this = min(ringqPutBlkMax(rq), size);
|
}
|
}
|
|
|
memcpy(rq->endp, buf, this);
|
memcpy(rq->endp, buf, this);
|
buf += this;
|
buf += this;
|
rq->endp += this;
|
rq->endp += this;
|
size -= this;
|
size -= this;
|
bytes_put += this;
|
bytes_put += this;
|
|
|
if (rq->endp >= rq->endbuf) {
|
if (rq->endp >= rq->endbuf) {
|
rq->endp = rq->buf;
|
rq->endp = rq->buf;
|
}
|
}
|
}
|
}
|
return bytes_put;
|
return bytes_put;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Get a block of data from the ringq. Return the number of bytes returned.
|
* Get a block of data from the ringq. Return the number of bytes returned.
|
*/
|
*/
|
|
|
int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size)
|
int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size)
|
{
|
{
|
int this, bytes_read;
|
int this, bytes_read;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(buf);
|
a_assert(buf);
|
a_assert(0 <= size && size < rq->buflen);
|
a_assert(0 <= size && size < rq->buflen);
|
|
|
/*
|
/*
|
* Loop getting the maximum bytes we can get in a single straight line copy
|
* Loop getting the maximum bytes we can get in a single straight line copy
|
*/
|
*/
|
bytes_read = 0;
|
bytes_read = 0;
|
while (size > 0) {
|
while (size > 0) {
|
this = ringqGetBlkMax(rq);
|
this = ringqGetBlkMax(rq);
|
this = min(this, size);
|
this = min(this, size);
|
if (this <= 0) {
|
if (this <= 0) {
|
break;
|
break;
|
}
|
}
|
|
|
memcpy(buf, rq->servp, this);
|
memcpy(buf, rq->servp, this);
|
buf += this;
|
buf += this;
|
rq->servp += this;
|
rq->servp += this;
|
size -= this;
|
size -= this;
|
bytes_read += this;
|
bytes_read += this;
|
|
|
if (rq->servp >= rq->endbuf) {
|
if (rq->servp >= rq->endbuf) {
|
rq->servp = rq->buf;
|
rq->servp = rq->buf;
|
}
|
}
|
}
|
}
|
return bytes_read;
|
return bytes_read;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Return the maximum number of bytes the ring q can accept via a single
|
* Return the maximum number of bytes the ring q can accept via a single
|
* block copy. Useful if the user is doing their own data insertion.
|
* block copy. Useful if the user is doing their own data insertion.
|
*/
|
*/
|
|
|
int ringqPutBlkMax(ringq_t *rq)
|
int ringqPutBlkMax(ringq_t *rq)
|
{
|
{
|
int space, in_a_line;
|
int space, in_a_line;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
space = rq->buflen - RINGQ_LEN(rq) - 1;
|
space = rq->buflen - RINGQ_LEN(rq) - 1;
|
in_a_line = rq->endbuf - rq->endp;
|
in_a_line = rq->endbuf - rq->endp;
|
|
|
return min(in_a_line, space);
|
return min(in_a_line, space);
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Return the maximum number of bytes the ring q can provide via a single
|
* Return the maximum number of bytes the ring q can provide via a single
|
* block copy. Useful if the user is doing their own data retrieval.
|
* block copy. Useful if the user is doing their own data retrieval.
|
*/
|
*/
|
|
|
int ringqGetBlkMax(ringq_t *rq)
|
int ringqGetBlkMax(ringq_t *rq)
|
{
|
{
|
int len, in_a_line;
|
int len, in_a_line;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
|
|
len = RINGQ_LEN(rq);
|
len = RINGQ_LEN(rq);
|
in_a_line = rq->endbuf - rq->servp;
|
in_a_line = rq->endbuf - rq->servp;
|
|
|
return min(in_a_line, len);
|
return min(in_a_line, len);
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Adjust the endp pointer after the user has copied data into the queue.
|
* Adjust the endp pointer after the user has copied data into the queue.
|
*/
|
*/
|
|
|
void ringqPutBlkAdj(ringq_t *rq, int size)
|
void ringqPutBlkAdj(ringq_t *rq, int size)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(0 <= size && size < rq->buflen);
|
a_assert(0 <= size && size < rq->buflen);
|
|
|
rq->endp += size;
|
rq->endp += size;
|
if (rq->endp >= rq->endbuf) {
|
if (rq->endp >= rq->endbuf) {
|
rq->endp -= rq->buflen;
|
rq->endp -= rq->buflen;
|
}
|
}
|
/*
|
/*
|
* Flush the queue if the endp pointer is corrupted via a bad size
|
* Flush the queue if the endp pointer is corrupted via a bad size
|
*/
|
*/
|
if (rq->endp >= rq->endbuf) {
|
if (rq->endp >= rq->endbuf) {
|
error(E_L, E_LOG, T("Bad end pointer"));
|
error(E_L, E_LOG, T("Bad end pointer"));
|
ringqFlush(rq);
|
ringqFlush(rq);
|
}
|
}
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Adjust the servp pointer after the user has copied data from the queue.
|
* Adjust the servp pointer after the user has copied data from the queue.
|
*/
|
*/
|
|
|
void ringqGetBlkAdj(ringq_t *rq, int size)
|
void ringqGetBlkAdj(ringq_t *rq, int size)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(rq->buflen == (rq->endbuf - rq->buf));
|
a_assert(0 < size && size < rq->buflen);
|
a_assert(0 < size && size < rq->buflen);
|
|
|
rq->servp += size;
|
rq->servp += size;
|
if (rq->servp >= rq->endbuf) {
|
if (rq->servp >= rq->endbuf) {
|
rq->servp -= rq->buflen;
|
rq->servp -= rq->buflen;
|
}
|
}
|
/*
|
/*
|
* Flush the queue if the servp pointer is corrupted via a bad size
|
* Flush the queue if the servp pointer is corrupted via a bad size
|
*/
|
*/
|
if (rq->servp >= rq->endbuf) {
|
if (rq->servp >= rq->endbuf) {
|
error(E_L, E_LOG, T("Bad serv pointer"));
|
error(E_L, E_LOG, T("Bad serv pointer"));
|
ringqFlush(rq);
|
ringqFlush(rq);
|
}
|
}
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Flush all data in a ring q. Reset the pointers.
|
* Flush all data in a ring q. Reset the pointers.
|
*/
|
*/
|
|
|
void ringqFlush(ringq_t *rq)
|
void ringqFlush(ringq_t *rq)
|
{
|
{
|
a_assert(rq);
|
a_assert(rq);
|
|
|
rq->servp = rq->buf;
|
rq->servp = rq->buf;
|
rq->endp = rq->buf;
|
rq->endp = rq->buf;
|
*rq->servp = '\0';
|
*rq->servp = '\0';
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/*
|
/*
|
* Grow the buffer. Return true if the buffer can be grown. Grow using
|
* Grow the buffer. Return true if the buffer can be grown. Grow using
|
* the increment size specified when opening the ringq. Don't grow beyond
|
* the increment size specified when opening the ringq. Don't grow beyond
|
* the maximum possible size.
|
* the maximum possible size.
|
*/
|
*/
|
|
|
static int ringq_grow(ringq_t *rq)
|
static int ringq_grow(ringq_t *rq)
|
{
|
{
|
unsigned char *newbuf;
|
unsigned char *newbuf;
|
int len;
|
int len;
|
|
|
a_assert(rq);
|
a_assert(rq);
|
|
|
if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) {
|
if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) {
|
return 0;
|
return 0;
|
}
|
}
|
|
|
len = ringqLen(rq);
|
len = ringqLen(rq);
|
|
|
if ((newbuf = balloc(B_L, rq->buflen + rq->increment)) == NULL) {
|
if ((newbuf = balloc(B_L, rq->buflen + rq->increment)) == NULL) {
|
return 0;
|
return 0;
|
}
|
}
|
ringqGetBlk(rq, newbuf, ringqLen(rq));
|
ringqGetBlk(rq, newbuf, ringqLen(rq));
|
bfree(B_L, (char*) rq->buf);
|
bfree(B_L, (char*) rq->buf);
|
|
|
#if OLD
|
#if OLD
|
rq->endp = &newbuf[endp];
|
rq->endp = &newbuf[endp];
|
rq->servp = &newbuf[servp];
|
rq->servp = &newbuf[servp];
|
rq->endbuf = &newbuf[rq->buflen];
|
rq->endbuf = &newbuf[rq->buflen];
|
rq->buf = newbuf;
|
rq->buf = newbuf;
|
#endif
|
#endif
|
|
|
rq->buflen += rq->increment;
|
rq->buflen += rq->increment;
|
rq->endp = newbuf;
|
rq->endp = newbuf;
|
rq->servp = newbuf;
|
rq->servp = newbuf;
|
rq->buf = newbuf;
|
rq->buf = newbuf;
|
rq->endbuf = &rq->buf[rq->buflen];
|
rq->endbuf = &rq->buf[rq->buflen];
|
|
|
ringqPutBlk(rq, newbuf, len);
|
ringqPutBlk(rq, newbuf, len);
|
return 1;
|
return 1;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|