/* fifo.c */
/* $Id: fifo.c,v 1.2 1992/10/11 15:15:57 nils Exp $ */
#include <stdio.h>
#include "externs.h"
#include "nalloc.h"
#include "fifo.h"
#include "db.h"
#include "config.h"
#define NULL 0
static NALLOC *na=NULL; /* fifo memory allocation */
FIFO *fi_open(fi,size)
FIFO *fi;
int size;
{
FIFO *ifi=fi;
if (!fi)
fi=(FIFO *)malloc(sizeof(FIFO));
fi->maxblk=size/FI_BSIZE;
fi->hoff=fi->toff=0;
fi->blocks=0;
if (!na)
na=na_open(sizeof(FI_BLK));
fi->head=fi->tail=(FI_BLK *)na_get(na);
fi->flags=(ifi) ? 0 : FI_FREE;
return(fi);
}
void fi_close(fi)
FIFO *fi;
{
FI_BLK *t,*t1;
fi->tail->next=NULL;
for(t=fi->head;t;t=t1)
{
t1=t->next;
na_free(na,t);
}
if (fi->flags & FI_FREE)
free(fi);
}
void fi_flush(fi)
FIFO *fi;
{
FI_BLK *t,*t1;
fi->tail->next=NULL;
for(t=fi->head;t;t=t1)
{
t1=t->next;
na_free(na,t);
}
fi->head=fi->tail=(FI_BLK *)na_get(na);
fi->toff=fi->hoff=0;
}
/* write returns 0 for total failure or 1 for success no inbetweens */
int fi_write(fi,buff,size)
FIFO *fi;
char *buff;
int size;
{
if (fi->blocks>fi->maxblk)
return(0);
while(size)
{
int asize;
asize=(size>(FI_BSIZE-fi->toff)) ? FI_BSIZE-fi->toff : size;
memcpy(&fi->tail->blk[fi->toff],buff,asize);
fi->toff+=asize;
buff+=asize;
size-=asize;
/* see if we need to add a new block */
if (fi->toff==FI_BSIZE)
{
fi->tail=(fi->tail->next=(FI_BLK *)na_get(na));
fi->blocks++;
fi->toff=0;
}
}
/* used by fi_gets to know if fifo has been updated */
fi->flags|=FI_CHANGE;
return(1);
}
/* remove # of characters from fifo with no read */
void fi_munch(fi,size)
FIFO *fi;
int size;
{
while(size && ((fi->head!=fi->tail) || (fi->toff!=fi->hoff)))
{
int asize=((fi->head==fi->tail) ? fi->toff : FI_BSIZE)-fi->hoff;
if (asize>size)
asize=size;
fi->hoff+=asize;
size-=asize;
/* if head at end of block then move to next and free it */
if (fi->hoff==FI_BSIZE)
{
FI_BLK *next=fi->head->next;
fi->hoff=0;
na_free(na,fi->head);
fi->blocks--;
fi->head=next;
}
}
}
/* returns a pointer + # of available chars, munch # of chars used after */
int fi_rread(fi,buf)
FIFO *fi;
char **buf;
{
*buf= &fi->head->blk[fi->hoff];
return(((fi->head==fi->tail) ? fi->toff : FI_BSIZE)-fi->hoff);
}
/* get a string from fifo terminated by \n, returns pointer on sucess or 0 on
failure, Note: \n is not included in string */
char *fi_gets(fi,buff,size)
FIFO *fi;
char *buff;
int size;
{
char *s;
FI_BLK *blk;
int off;
int munch=0;
size--;
/* don't try again until fifo updated */
if ((fi->flags & FI_FAILED) && !(fi->flags & FI_CHANGE))
return(0);
fi->flags&=~(FI_FAILED & FI_CHANGE);
/* scan fifo for \n */
s=buff;
blk=fi->head;
off=fi->hoff;
while(size)
{
int asize=((blk==fi->tail) ? fi->toff : FI_BSIZE)-off;
if (asize>size)
asize=size;
size-=asize;
while(asize)
{
char c;
c= *s++=blk->blk[off++];
munch++;
asize--;
/* finally found it */
if (c=='\n' || c=='\r') /* accept either \n or \r */
{
s[-1]=0;
fi_munch(fi,munch);
return(buff);
}
}
/* no luck */
if (size && (blk==fi->tail))
{
fi->flags|=FI_FAILED;
return(0);
}
/* next block */
blk=blk->next;
off=0;
}
*s++=0;
fi_munch(fi,munch);
return(buff);
}
/*main()
{
char buff[100];
int a;
FIFO *fi=fi_open(NULL,20000);
char *s="This\nIs\nA test\nof the\nemergency\ncat\neating system\n";
while(1)
{
for(a=0;a<(rand() & 15);a++)
fi_write(fi,s,strlen(s));
while(fi_gets(fi,buff,100) && ((rand() & 31)!=1))
printf("[[%s]]\n",buff);
}
}*/