aboutsummaryrefslogtreecommitdiff
path: root/src/base/bufio/getc.c
diff options
context:
space:
mode:
authorNicholas <nbnoll@eml.cc>2021-11-20 20:12:21 -0800
committerNicholas <nbnoll@eml.cc>2021-11-20 20:12:21 -0800
commit138fb272fae79587de3469493b55e4d18eadc722 (patch)
tree447d2af80b8c2ea080253e76d33e128c9b27d3f6 /src/base/bufio/getc.c
parentc9a32c1a43d2bdded07eaa45732c3a6e195a5442 (diff)
Feat: added buffered io from plan9
As we no longer have the FILE type, we need to buffer our reading and writing so that we don't have to make so many syscalls. The API is nice so that we can buffer other readers. We will update it so that it eats io·Readers/io·Writers.
Diffstat (limited to 'src/base/bufio/getc.c')
-rw-r--r--src/base/bufio/getc.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/base/bufio/getc.c b/src/base/bufio/getc.c
new file mode 100644
index 0000000..264e01d
--- /dev/null
+++ b/src/base/bufio/getc.c
@@ -0,0 +1,45 @@
+#include "internal.h"
+
+int
+bio·getc(io·Header *io)
+{
+ int i;
+ intptr nr;
+
+loop:
+ i = io->ilen;
+ if(i != 0){
+ io->ilen = i+1;
+ return io->e[i];
+ }
+
+ if(io->state != io·BufRdr){
+ if(io->state == io·BufEnd)
+ io->state = io·BufRdr;
+ return io·BufEof;
+ }
+
+ /*
+ * get next buffer, try to keep io·BufUngets bytes
+ * pre-catenated from the previous read to allow for ungets
+ */
+ mem·move(io->b-io·BufUngets, io->e-io·BufUngets, io·BufUngets);
+ if(sys·read(io->fd, io->cap, io->b, &nr)){
+ io->state = io·BufNil;
+ return io·BufEof;
+ }
+ if(nr == 0){
+ io->state = io·BufEnd;
+ return io·BufEof;
+ }
+
+ if(nr < io->cap){
+ mem·move(io->e-i-io·BufUngets, io->b-io·BufUngets, i+io·BufUngets);
+ io->g = io->e-i;
+ }
+
+ io->ilen = -i;
+ io->pos += +i;
+
+ goto loop;
+}