aboutsummaryrefslogtreecommitdiff
path: root/sys/base/bufio
diff options
context:
space:
mode:
Diffstat (limited to 'sys/base/bufio')
-rw-r--r--sys/base/bufio/dump.c66
-rw-r--r--sys/base/bufio/get.c17
-rw-r--r--sys/base/bufio/internal.h4
-rw-r--r--sys/base/bufio/read.c36
-rw-r--r--sys/base/bufio/reader.c28
-rw-r--r--sys/base/bufio/refill.h28
-rw-r--r--sys/base/bufio/rules.mk5
-rw-r--r--sys/base/bufio/unget.c18
8 files changed, 202 insertions, 0 deletions
diff --git a/sys/base/bufio/dump.c b/sys/base/bufio/dump.c
new file mode 100644
index 0000000..0b527e2
--- /dev/null
+++ b/sys/base/bufio/dump.c
@@ -0,0 +1,66 @@
+// -----------------------------------------------------------------------
+// reader
+
+#if 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;
+}
+#endif
+
+// -----------------------------------------------------------------------
+// writer
diff --git a/sys/base/bufio/get.c b/sys/base/bufio/get.c
new file mode 100644
index 0000000..9f10c88
--- /dev/null
+++ b/sys/base/bufio/get.c
@@ -0,0 +1,17 @@
+#include "internal.h"
+#include "refill.h"
+
+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;
+}
diff --git a/sys/base/bufio/internal.h b/sys/base/bufio/internal.h
new file mode 100644
index 0000000..302c035
--- /dev/null
+++ b/sys/base/bufio/internal.h
@@ -0,0 +1,4 @@
+#pragma once
+
+#include <u.h>
+#include <base.h>
diff --git a/sys/base/bufio/read.c b/sys/base/bufio/read.c
new file mode 100644
index 0000000..09a9f83
--- /dev/null
+++ b/sys/base/bufio/read.c
@@ -0,0 +1,36 @@
+#include "internal.h"
+#include "refill.h"
+
+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;
+}
diff --git a/sys/base/bufio/reader.c b/sys/base/bufio/reader.c
new file mode 100644
index 0000000..afdaf60
--- /dev/null
+++ b/sys/base/bufio/reader.c
@@ -0,0 +1,28 @@
+#include "internal.h"
+
+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 };
+}
diff --git a/sys/base/bufio/refill.h b/sys/base/bufio/refill.h
new file mode 100644
index 0000000..41e357e
--- /dev/null
+++ b/sys/base/bufio/refill.h
@@ -0,0 +1,28 @@
+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;
+}
diff --git a/sys/base/bufio/rules.mk b/sys/base/bufio/rules.mk
new file mode 100644
index 0000000..84f283f
--- /dev/null
+++ b/sys/base/bufio/rules.mk
@@ -0,0 +1,5 @@
+SRCS_$(d)+=\
+ $(d)/bufio/get.c\
+ $(d)/bufio/read.c\
+ $(d)/bufio/reader.c\
+ $(d)/bufio/unget.c\
diff --git a/sys/base/bufio/unget.c b/sys/base/bufio/unget.c
new file mode 100644
index 0000000..3fd16de
--- /dev/null
+++ b/sys/base/bufio/unget.c
@@ -0,0 +1,18 @@
+#include "internal.h"
+
+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;
+}