/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#ifndef lint
static char RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/sbuf.c,v 1.1 92/02/09 22:59:34 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);
}
}