/* buffer/ph_buffer.c.  Generated from buffer.c.in by configure. */

/*
**  Copyright 1998-2004 University of Illinois Board of Trustees
**  Copyright 1998-2004 Mark D. Roth
**  All rights reserved.
**
**  ph_buffer.c - network line buffer code
**
**  Mark D. Roth <roth@uiuc.edu>
**  Campus Information Technologies and Educational Services
**  University of Illinois at Urbana-Champaign
*/

#include <config.h>
#include <compat.h>

#include <ph_buffer.h>

#include <stdio.h>
#include <errno.h>

#ifdef STDC_HEADERS
# include <string.h>
#endif


struct ph_buffer
{
	char *b_buf;
	size_t b_bufsize;
	char *b_readp;
	char *b_writep;
	ph_read_func_t b_readfunc;
	void *b_app_data;
};


int
ph_buffer_new(ph_buffer_t *bufp,
			   size_t bufsize,
			   ph_read_func_t readfunc,
			   void *app_data)
{
	*bufp = (ph_buffer_t)calloc(1, sizeof(struct ph_buffer));
	if (*bufp == NULL)
		return -1;

	(*bufp)->b_buf = (char *)calloc(1, bufsize);
	if ((*bufp)->b_buf == NULL)
		return -1;

	(*bufp)->b_readp = (*bufp)->b_writep = (*bufp)->b_buf;
	(*bufp)->b_bufsize = bufsize;
	(*bufp)->b_readfunc = readfunc;
	(*bufp)->b_app_data = app_data;

	return 0;
}


#define BUF_FREE_LEN(buf) \
	(((buf)->b_bufsize - 1) - ((buf)->b_writep - (buf)->b_buf))


ssize_t
ph_buffer_read_line(ph_buffer_t buf,
				 char *callbuf, size_t callbuflen)
{
	char *linep;
	ssize_t sz;
	size_t retlen;

	/* keep reading until we have a line in the buffer */
	while (strchr(buf->b_readp, '\n') == NULL)
	{
		sz = (*(buf->b_readfunc))(buf->b_app_data, buf->b_writep,
					  BUF_FREE_LEN(buf));
		if (sz == 0)
		{
			errno = ECONNRESET;
			return -1;
		}
		if (sz == (ssize_t)-1)
			return -1;
		buf->b_writep += sz;
		*(buf->b_writep) = '\0';
	}

	/* chop off the first line and move read pointer */
	linep = strsep(&(buf->b_readp), "\n");

	/* copy line to caller-suppied buffer */
	retlen = strlcpy(callbuf, linep, callbuflen);

	/* move remaining data to beginning of buffer and update pointers */
	sz = buf->b_writep - buf->b_readp;
	memmove(buf->b_buf, buf->b_readp, sz + 1);
	buf->b_writep = buf->b_buf + sz;
	buf->b_readp = buf->b_buf;

	return retlen;
}


void
ph_free(ph_buffer_t buf)
{
	if (buf->b_buf != NULL)
		free(buf->b_buf);
	free(buf);
}




syntax highlighted by Code2HTML, v. 0.9.1