/* --------------------------------------------------------------------------
* Copyright 2003-2011 (inclusive) Nathan Angelacos
* (nangel@users.sourceforge.net)
*
* This file is part of haserl.
*
* Haserl is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* Haserl 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with haserl. If not, see .
*
* ------------------------------------------------------------------------ */
#if HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include "sliding_buffer.h"
/*
* initialize a sliding buffer structure
*/
int
s_buffer_init (sliding_buffer_t * sbuf, int size)
{
sbuf->maxsize = size;
sbuf->buf = malloc (sbuf->maxsize);
/* reduce maxsize by one, so that you can add a NULL to the end of any
returned token and not have a memory overwrite */
sbuf->maxsize -= 1;
sbuf->fh = 0; /* use stdin by default */
sbuf->eof = 0;
sbuf->len = 0;
sbuf->ptr = sbuf->buf;
sbuf->bufsize = 0;
sbuf->maxread = 0;
sbuf->nrread = 0;
return (sbuf->buf != NULL); /* return true if the alloc succeeded */
}
/*
* destroy a sliding buffer structure
*/
void
s_buffer_destroy (sliding_buffer_t * sbuf)
{
free (sbuf->buf);
}
/*
* read the next segment from a sliding buffer. returns !=0 if the
* segment ends at a matchstr token, or if we are at the end of the string
* returns 0 if the segment does not end
*/
int
s_buffer_read (sliding_buffer_t * sbuf, char *matchstr)
{
int len, pos;
int r;
/*
* if eof and ptr ran off the buffer, then we are done
*/
if ((sbuf->eof) && (sbuf->ptr > sbuf->buf))
{
return 0;
}
/*
* if need to fill the buffer, do so
*/
if ((sbuf->bufsize == 0) ||
(sbuf->ptr >= (sbuf->buf + sbuf->bufsize - strlen (matchstr))))
{
len = sbuf->bufsize - (sbuf->ptr - sbuf->buf);
if (len)
{
memmove (sbuf->buf, sbuf->ptr, len);
}
sbuf->ptr = sbuf->buf;
sbuf->bufsize = len;
/* if the filedescriptor is invalid, we are obviously
* at an end of file condition.
*/
if (fcntl (sbuf->fh, F_GETFL) == -1)
{
r = 0;
}
else
{
size_t n = sbuf->maxsize - len;
if (sbuf->maxread && sbuf->maxread < sbuf->nrread + n)
n = sbuf->maxread - sbuf->nrread;
r = read (sbuf->fh, sbuf->buf + len, n);
}
/*
* only report eof when we've done a read of 0.
*/
if (r == 0 || (r < 0 && errno != EINTR))
{
sbuf->eof = -1;
}
else
{
sbuf->bufsize += (r > 0) ? r : 0;
sbuf->nrread += (r > 0) ? r : 0;
}
}
/*
* look for the matchstr
*/
pos = 0;
len = sbuf->bufsize - (int) (sbuf->ptr - sbuf->buf) - strlen (matchstr);
while (memcmp (matchstr, sbuf->ptr + pos, strlen (matchstr)) && (pos < len))
{
pos++;
}
/*
* if we found it
*/
if (pos < len)
{
sbuf->len = pos;
sbuf->segment = sbuf->ptr;
sbuf->ptr = sbuf->segment + pos + strlen (matchstr);
return -1;
}
if (sbuf->eof)
{
len += strlen (matchstr);
}
/*
* ran off the end, didn't find the matchstr
*/
sbuf->segment = sbuf->ptr;
sbuf->len = len;
sbuf->ptr += sbuf->len;
return (sbuf->eof) ? (-1) : (0);
}
#ifdef TEST_FRAMEWORK
main ()
{
int x;
sliding_buffer_t sb;
char foo[200];
s_buffer_init (&sb, 32);
do
{
x = s_buffer_read (&sb, "&");
sprintf (foo, "%03d- %03d - %03d", x, sb.eof, sb.len);
write (1, foo, strlen (foo));
write (1, sb.segment, sb.len);
write (1, "\n", 1);
}
while ((!sb.eof));
s_buffer_destroy (&sb);
}
#endif