From 21055a1e5d34dda1b8151dd46a6bedca22bd73d9 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 18 Apr 2020 13:40:53 -0700 Subject: feat: added prototype of io/buffered io --- src/bufio/writer.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/bufio/writer.c (limited to 'src/bufio/writer.c') diff --git a/src/bufio/writer.c b/src/bufio/writer.c new file mode 100644 index 0000000..07573d5 --- /dev/null +++ b/src/bufio/writer.c @@ -0,0 +1,95 @@ +#include "impl.h" + +struct bufio·Writer +{ + io·Writer w; + Buffer buf; +}; + +// Constructor/destructor. + +bufio·Writer* +bufio·newwriter(io·Writer w) +{ + bufio·Writer* bw = newbuffer(offsetof(bufio·Writer, buf), 0); + bw->w = w; + bw->buf.pos = bw->buf.base; + + return bw; +} + +error +bufio·freewriter(bufio·Writer* w) +{ + free(w); + + return 0; +} + +// Write will write n bytes from the input buffer into the storage buffer. +// Returns the actual number of bytes written. +int +bufio·write(bufio·Writer* w, byte* buf, int count) +{ + int remain = count; + byte* wtr = buf; + + int n, nw; + while (remain > 0) { + int bdiff = w->buf.end - w->buf.pos; + n = (bdiff > remain) ? remain : bdiff; + if (!n) { + if (w->buf.eof) break; + nw = w->w.write(w->w.impl, buf, count); + if (nw < w->buf.size) { + w->buf.eof = 1; + return BUF·err; + } + w->buf.off += nw; + w->buf.pos = w->buf.base; + } + memmove(w->buf.pos, wtr, n); + wtr += n; + w->buf.pos += n; + remain -= n; + } + + return count - remain; +} + +error +bufio·put(bufio·Writer* w, byte c) +{ + int diff; +putbyte: + diff = w->buf.end - w->buf.pos; + if (diff) { + *w->buf.pos++ = c; + return 0; + } + if (bufio·flush(w) != BUF·err) goto putbyte; + + return BUF·err; +} + +error +bufio·flush(bufio·Writer* w) +{ + int active = (w->buf.eof == 0); + + int n, nw; + if (active && w) { + n = w->buf.pos - w->buf.base; + if (!n) return 0; + + nw = w->w.write(w->w.impl, w->buf.base, n); + if (nw == n) { + w->buf.off += n; + return 0; + } + w->buf.eof = 1; + w->buf.pos = w->buf.end; + } + + return BUF·err; +} -- cgit v1.2.1