/* fifo.c */ #include "fifo.h" #include "nalloc.h" #define NULL 0 static NALLOC *na = NULL; 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') { 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); }