/* 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); } }*/