#include "impl.h" struct bufio·Reader { io·Reader r; Buffer buf; }; bufio·Reader* bufio·newreader(io·Reader r) { bufio·Reader* br = newbuffer(offsetof(bufio·Reader, buf), 0); br->r = r; br->buf.pos = br->buf.end; return br; } error bufio·freereader(bufio·Reader* r) { free(r); return 0; } static int refill(bufio·Reader* r) { if (r->buf.eof) return BUF·err; int nr = r->r.read(r->r.impl, r->buf.base, r->buf.size); if (nr <= 0) { r->buf.eof = 1; goto end; } r->buf.off += nr; r->buf.pos = r->buf.base; if (nr < r->buf.size) { int d = (r->buf.size - nr); r->buf.eof = 1; memmove(r->buf.pos + d, r->buf.pos, nr); memmove(r->buf.pos + d - BUF·ungets, r->buf.b, BUF·ungets); r->buf.pos += d; } end: return nr; } // Read will attempt to read n bytes from the buffer, starting at the offet // offset. Returns the actual number of bytes read from the stream. Input buf // can not alias b int bufio·read(bufio·Reader* r, byte* buf, int count) { if (count == 0 || buf == nil || r->buf.off == BUF·eof) return BUF·err; int remain = count; byte* rdr = buf; int n, nr; while (remain) { int bdiff = r->buf.end - r->buf.pos; n = (bdiff > remain) ? remain : bdiff; if (!n) { if (r->buf.eof | (refill(r) <= 0)) break; } memmove(rdr, r->buf.pos, n); rdr += n; r->buf.pos += n; remain -= n; } return count - remain; } int bufio·readln(bufio·Reader* r, byte* buf, int count, error* err) { byte *it, *end, *cnt; int nb; Search: nb = 0; cnt = r->buf.pos + count; end = MIN(r->buf.end, cnt); for (it = r->buf.pos; it != end && *it != EOF; ++it, nb++) { if (*it == '\n') { *err = 0; goto End; } } if (it == r->buf.end) { memmove(buf, r->buf.pos, nb); r->buf.pos = r->buf.end; if (refill(r) <= 0) { *err = 1; return nb; } Assert(nb < count); count -= nb; buf += nb; goto Search; } if (it == cnt) { Assert(nb == count); *err = 2; } Assert(*it == EOF || *err == 2); End: memmove(buf, r->buf.pos, nb); r->buf.pos = it; return nb; } // advanceBuffer moves the buffer ahead by n without reading. void bufio·discard(bufio·Reader* r, int count) { if (count > BUF·max) panicf("can't discard %d bytes", count); byte stack[BUF·max]; bufio·read(r, stack, count); } // ReadByte reads a single byte from the buffered stream. byte bufio·get(bufio·Reader* r) { getbyte: if (r->buf.pos < r->buf.end) { return *r->buf.pos++; } memmove(r->buf.b, r->buf.end - BUF·ungets, BUF·ungets); if (refill(r) <= 0) { return EOF; } goto getbyte; } error bufio·unget(bufio·Reader* r) { if (r->buf.pos == r->buf.b) { return BUF·err; } r->buf.pos--; return 0; } byte bufio·peek(bufio·Reader* r) { if (r->buf.pos != r->buf.end) return *r->buf.pos; byte* old = r->buf.pos; byte c = bufio·get(r); if (r->buf.pos != old && (bufio·unget(r) == BUF·err)) { panicf("buffer failure, can't move backwards"); } return c; } // peekBytes has the same behavior as read, but doesn't advance the buffer. int bufio·peekfor(bufio·Reader* r, byte* buf, int count) { if (count == 0 || buf == nil) return 0; int delta = r->buf.end - r->buf.pos; if (delta > count) { memcpy(buf, r->buf.pos, count); return count; } byte c, *it; for (it = buf; it != buf + count; ++it) { c = bufio·get(r); *it = c; if (c == EOF) break; } int diff = it - buf; for (int n = 0; n < diff; n++) { bufio·unget(r); } return diff; } void bufio·clear(bufio·Reader* r) { memset(r->buf.b, 0, r->buf.size); }