/* This file is in the public domain. */ /* * There's little to add to individual functions here beyond what * linereader.h says. * * We do our own pseudo-stdio, with ibuf/ibfill/ibptr buffering chunks * of data and handing out one char at a time to build up lines. We * could gain a bit of efficiency in common cases by handing out lines * directly from ibuf, but the code complexity does not strike me as * worth the speedup. This code is used only for config file parsing, * which is hardly time-critical, so I come down in favour of simple. */ #include #include #include "linereader.h" struct linereader { unsigned int flags; #define LRF_EOF 0x00000001 #define LRF_ERROR 0x00000002 int fd; unsigned char ibuf[8192]; int ibfill; int ibptr; unsigned char *lb; int ll; int la; int lno; } ; LINEREADER *lr_setup(int fd) { LINEREADER *lr; lr = malloc(sizeof(LINEREADER)); lr->flags = 0; lr->fd = fd; lr->ibfill = 0; lr->ibptr = 0; lr->lb = 0; lr->ll = 0; lr->la = 0; lr->lno = 0; return(lr); } void lr_done(LINEREADER *lr) { free(lr->lb); free(lr); } LRGLSTAT lr_getline(LINEREADER *lr) { int c; void save(char ch) { if (lr->ll >= lr->la) lr->lb = realloc(lr->lb,lr->la=lr->ll+8); lr->lb[lr->ll++] = ch; } if (lr->flags & LRF_EOF) return(LRGL_EOF); if (lr->flags & LRF_ERROR) return(LRGL_ERROR); lr->ll = 0; while <"reading"> (1) { if (lr->ibptr >= lr->ibfill) { lr->ibptr = 0; lr->ibfill = read(lr->fd,&lr->ibuf[0],sizeof(lr->ibuf)); if (lr->ibfill < 0) { lr->flags |= LRF_ERROR; return(LRGL_ERROR); } if (lr->ibfill == 0) { lr->flags |= LRF_EOF; if (lr->ll > 0) break <"reading">; return(LRGL_EOF); } } c = lr->ibuf[lr->ibptr++]; if (c == '\n') break <"reading">; save(c); } save('\0'); lr->ll --; lr->lno ++; return(LRGL_LINE); } const char *lr_ptr(LINEREADER *lr) { return(lr->lb); } int lr_lineno(LINEREADER *lr) { return(lr->lno); }