/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/sbuf.c,v 1.2 91/08/07 00:48:39 mjr Exp $";
#endif

/* configure all options BEFORE including system stuff. */
#include	"config.h"


#include	<stdio.h>

#include	"mud.h"
#include	"sbuf.h"


/* increment to stretch a stretchy buffer by */
#define	SBUF_INCR	256


char
_sbufgrow(c,b)
char	c;
Sbuf	*b;
{
	char	*xp;

	if(b == (Sbuf *)0)
		return('\0');

	if(b->buf == (char *)0) {
		b->bsiz = SBUF_INCR;
		if((b->buf = (char *)malloc(b->bsiz)) == (char *)0)
			return('\0');

		b->bc = b->bsiz;
		b->bp = b->buf;
	} else {
		int	xoff = (int)(b->bp - b->buf);

		b->bsiz += SBUF_INCR;

		/* disaster */
		if((xp = (char *)realloc((mall_t)b->buf,(unsigned)b->bsiz)) == (char *)0) {
			b->bp = (char *)0;
			b->bc = 0;
			b->bsiz = 0;
			return('\0');
		}
		b->buf = xp;
		b->bp = xp + xoff;
		b->bc = SBUF_INCR;
	}

	b->bc--;
	return(*(b->bp)++ = c);
}




/* reset a stretchy buffer to a clean slate. */
void
sbuf_reset(b)
Sbuf	*b;
{
	if(b == (Sbuf *)0 || b->buf == (char *)0)
		return;

	/* figure out the average size used so far - DO FIRST! */
	if(b->bp != b->buf && b->rct < 100000) {
		b->avg = ((b->avg * b->rct) + sbuf_len(b)) / (b->rct + 1);
		b->rct++;
	}

	b->bp = b->buf;
	b->bc = b->bsiz - 1;
	*(b->bp) = '\0';

	/* if the buffer is statistically rather large, free it */
	if(b->bsiz > SBUF_INCR && b->bsiz > (b->avg + SBUF_INCR)) {
		(void)free((mall_t)b->buf);
		b->bp = b->buf = (char *)0;
		b->bsiz = 0;
		b->bc = 0;
	}
}




Sbuf	*
sbuf_new()
{
	Sbuf	*b;

	if((b = (Sbuf *)malloc(sizeof(Sbuf))) == (Sbuf *)0)
		return((Sbuf *)0);

	b->bp = (char *)0;
	b->buf = (char *)0;
	b->bc = b->bsiz = b->rct = b->avg = 0;
	return(b);
}




void
sbuf_free(b)
Sbuf	*b;
{
	if(b == (Sbuf *)0)
		return;

	if(b->buf != (char *)0)
		(void)free((mall_t)b->buf);

	/* in case some bonehead tries to use one after deallocation :) */
	b->bp = b->buf = (char *)0;
	b->bc = 0;
	b->bsiz = 0;

	free((mall_t)b);
}




void
sbuf_freestatic(b)
Sbuf	*b;
{
	if(b->buf != (char *)0)
		(void)free((mall_t)b->buf);
	b->bp = b->buf = (char *)0;
	b->bc = 0;
	b->bsiz = 0;
}




void
sbuf_initstatic(b)
Sbuf	*b;
{
	b->bp = b->buf = (char *)0;
	b->bc = 0;
	b->bsiz = 0;
	b->avg = b->rct = 0;
}




char	*
sbuf_strcpy(s,sb)
char	*s;
Sbuf	*sb;
{
	sbuf_reset(sb);
	while(*s != '\0') {
		sbuf_put(*s,sb);
		s++;
	}
	sbuf_put('\0',sb);
	return(sbuf_buf(sb));
}




char	*
sbuf_strcat(s,sb)
char	*s;
Sbuf	*sb;
{
	/* lose trailing null (if one) */
	if(sb->bp > sb->buf && *(sb->bp - 1) == '\0')
		sbuf_unput(sb);

	while(*s != '\0') {
		sbuf_put(*s,sb);
		s++;
	}
	sbuf_put('\0',sb);
	return(sbuf_buf(sb));
}




/*
read a line from a Buf into an Sbuf.
*/
char	*
sbuf_fgets(s,f)
FILE	*f;
Sbuf	*s;
{
	int	c;

	if(f == (FILE *)0 || s == (Sbuf *)0 || ferror(f))
		return((char *)0);

	sbuf_reset(s);
	while(1) {
		c = getc(f);
		if(c == EOF || ferror(f)) {
			if(s->bp == s->buf)
				return((char *)0);
			sbuf_put('\0',s);
			return(sbuf_buf(s));
		}
		if(c == '\n') {
			sbuf_put('\0',s);
			return(sbuf_buf(s));
		}
		sbuf_put(c,s);
	}
}