aboutsummaryrefslogtreecommitdiff
path: root/sys/base/bufio.c
diff options
context:
space:
mode:
authorNicholas Noll <nnoll523@gmail.com>2021-10-23 11:17:25 -0700
committerNicholas Noll <nnoll523@gmail.com>2021-10-26 11:11:57 -0700
commitc8e1e71eb526475dd431443345262c2e5a627831 (patch)
treeea9f7bcbba18a13f7ba8b32fcb1433ac2f4dd8b4 /sys/base/bufio.c
parent40f4c7305a041d4214df117491593898d04d0134 (diff)
chore(rename): libn -> base
Diffstat (limited to 'sys/base/bufio.c')
-rw-r--r--sys/base/bufio.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/sys/base/bufio.c b/sys/base/bufio.c
new file mode 100644
index 0000000..7ebee68
--- /dev/null
+++ b/sys/base/bufio.c
@@ -0,0 +1,190 @@
+#include <u.h>
+#include <base.h>
+
+// -----------------------------------------------------------------------
+// reader
+
+error
+bufio·initreader(io·Buffer *buf, io·Reader rdr, void *h)
+{
+ if (buf->state) {
+ errorf("attemped to initialize an active buffer, state is '%d'", buf->state);
+ return bufio·err;
+ }
+ buf->state = bufio·rdr;
+ buf->runesize = 0;
+ buf->h = h;
+ buf->rdr = rdr;
+ buf->beg = buf->buf + bufio·ungets;
+ buf->pos = buf->beg;
+ buf->end = buf->pos;
+ buf->size = bufio·size - bufio·ungets;
+
+ return 0;
+}
+
+void
+bufio·finireader(io·Buffer *buf)
+{
+ buf->state = bufio·nil;
+ buf->runesize = 0;
+ buf->rdr = (io·Reader){ .read = nil };
+}
+
+static
+int
+refill(io·Buffer *buf)
+{
+ int n;
+
+ if (buf->state & bufio·end) {
+ return bufio·err;
+ }
+ memcpy(buf->buf, buf->pos - bufio·ungets, bufio·ungets);
+
+ n = buf->rdr.read(buf->h, 1, buf->size, buf->beg);
+ if (n < 0)
+ return bufio·err;
+ if (n == 0) {
+ buf->state |= bufio·end;
+ return 0;
+ }
+
+ buf->pos = buf->beg;
+ buf->end = buf->pos + n;
+
+ // TEST: put a physical EOF byte at the end
+ // this would allow for an unget operation
+ if (n < buf->size)
+ *buf->end++ = EOF;
+
+ return n;
+}
+
+int
+bufio·getbyte(io·Buffer *buf)
+{
+getbyte:
+ if (buf->pos < buf->end) {
+ return *buf->pos++;
+ }
+
+ memmove(buf->buf, buf->end - bufio·ungets, bufio·ungets);
+
+ if (refill(buf) <= 0)
+ return bufio·eof;
+
+ goto getbyte;
+}
+
+error
+bufio·ungetbyte(io·Buffer *buf, byte c)
+{
+ if (!(buf->state & bufio·rdr)) {
+ errorf("attempted to unget on non-active reader");
+ return bufio·err;
+ }
+
+ if (buf->pos == buf->buf) {
+ errorf("attempted to unget past end of buffer");
+ return bufio·err;
+ }
+
+ buf->pos--;
+ return 0;
+}
+
+rune
+bufio·getrune(io·Buffer *buf)
+{
+ ubyte b;
+ int i;
+ byte str[UTFmax+1];
+ rune r;
+
+ // NOTE: I'm worried about the sign here...
+ b = bufio·getbyte(buf);
+ if (b < RuneSelf) {
+ buf->runesize = 1;
+ return b;
+ }
+
+ i = 0;
+ str[i++] = b;
+
+nextbyte:
+ b = bufio·getbyte(buf);
+ if (b < 0) return b;
+ if (i >= arrlen(str)) return RuneErr;
+ str[i++] = b;
+ if (!utf8·fullrune(str, i))
+ goto nextbyte;
+
+ buf->runesize = utf8·bytetorune(&r, str);
+ if (r == RuneErr && b == 1) {
+ errorf("illegal UTF-8 sequence");
+ for (; i >= 0; i--)
+ errorf("%s%.2x", i > 0 ? " " : "", *(ubyte*)(str+i));
+ errorf("\n");
+
+ buf->runesize = 0;
+ } else
+ for (; i > buf->runesize; i--)
+ bufio·ungetbyte(buf, str[i]);
+
+ return r;
+}
+
+// TODO: Check that we are given the correct rune!
+error
+bufio·ungetrune(io·Buffer *buf, rune r)
+{
+ if (buf->state & bufio·rdr) {
+ errorf("attempted to unget on non-active reader");
+ return bufio·err;
+ }
+
+ if (buf->pos == buf->buf) {
+ errorf("attempted to unget past end of buffer");
+ return bufio·err;
+ }
+
+ buf->pos -= buf->runesize;
+ return 0;
+}
+
+int
+bufio·read(io·Buffer *buf, int sz, int n, void *out)
+{
+ byte *wtr;
+ int nr, rem, diff;
+
+ if (n == 0 || buf->state & bufio·end)
+ return bufio·err;
+
+ assert(buf->state & bufio·rdr);
+
+ wtr = out;
+ rem = n*sz;
+ while (rem > 0) {
+ diff = buf->end - buf->pos;
+ nr = MIN(diff, rem);
+ if (!nr) {
+ if (buf->state & bufio·end)
+ break;
+ if (refill(buf) <= 0)
+ break;
+
+ continue;
+ }
+ memmove(wtr, buf->pos, nr);
+ wtr += nr;
+ buf->pos += nr;
+ rem -= nr;
+ }
+
+ return n - rem/sz;
+}
+
+// -----------------------------------------------------------------------
+// writer