/* This file is in the public domain. */ #include #include #include "memstream.h" typedef struct chunk CHUNK; struct chunk { CHUNK *link; unsigned char data[8000]; int fill; } ; struct memstream { CHUNK *chunks; CHUNK **chunkt; CHUNK *wcur; CHUNK *rcur; int rptr; int totalsize; } ; static void append_new_chunk(MEMSTREAM *m) { m->wcur = malloc(sizeof(CHUNK)); m->wcur->link = 0; *m->chunkt = m->wcur; m->chunkt = &m->wcur->link; m->wcur->fill = 0; } MEMSTREAM *memstream_open_w(void) { MEMSTREAM *m; m = malloc(sizeof(MEMSTREAM)); m->chunks = 0; m->chunkt = &m->chunks; m->wcur = 0; m->rcur = 0; m->rptr = 0; m->totalsize = 0; return(m); } void memstream_append(MEMSTREAM *m, const void *data, int len) { const char *dp; int n; if (len < 1) return; if (m->wcur == 0) append_new_chunk(m); dp = data; while (1) { n = sizeof(m->wcur->data) - m->wcur->fill; if (len <= n) { bcopy(dp,&m->wcur->data[m->wcur->fill],len); m->wcur->fill += len; m->totalsize += len; break; } bcopy(dp,&m->wcur->data[m->wcur->fill],n); m->wcur->fill += n; m->totalsize += n; append_new_chunk(m); dp += n; len -= n; } } void memstream_map(MEMSTREAM *m, void (*each)(const void *, int)) { CHUNK *c; for (c=m->chunks;c;c=c->link) (*each)(&c->data[0],c->fill); } void memstream_dump_stdio(MEMSTREAM *m, FILE *to) { CHUNK *c; for (c=m->chunks;c;c=c->link) fwrite(&c->data[0],1,c->fill,to); } unsigned int memstream_size(MEMSTREAM *m) { return(m->totalsize); } extern void memstream_free(MEMSTREAM *m) { CHUNK *c; while (1) { c = m->chunks; if (! c) break; m->chunks = c->link; free(c); } free(m); } void memstream_rewind_r(MEMSTREAM *m) { m->rcur = m->chunks; m->rptr = 0; } int memstream_readc(MEMSTREAM *m) { if (! m->rcur) return(-1); while (m->rptr >= m->rcur->fill) { m->rcur = m->rcur->link; m->rptr = 0; if (! m->rcur) return(-1); } return(m->rcur->data[m->rptr++]); } void memstream_read_lines(MEMSTREAM *m, void (*fn)(const char *, int)) { unsigned char *lb; int la; int ll; int c; void l_append(int ch) { if (ll >= la) lb = realloc(lb,la=ll+8); lb[ll++] = ch; } memstream_rewind_r(m); lb = 0; la = 0; while <"lines"> (1) { ll = 0; while (1) { c = memstream_readc(m); if (c < 0) { if (ll == 0) break <"lines">; break; } if (c == '\n') break; l_append(c); } l_append('\0'); ll --; (*fn)(lb,ll); } free(lb); }