aboutsummaryrefslogtreecommitdiff
path: root/src/base/io/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/io/read.c')
-rw-r--r--src/base/io/read.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/src/base/io/read.c b/src/base/io/read.c
index b0ed3d2..d4f7bd9 100644
--- a/src/base/io/read.c
+++ b/src/base/io/read.c
@@ -1,7 +1,54 @@
#include "internal.h"
-int
-io·read(io·Stream *s, int sz, int n, void *buf)
+intptr
+io·read(io·Header *io, intptr len, void *buf)
{
- return fread(buf, sz, n, s);
+ uchar *b;
+ intptr c0, c, nr, n, ic;
+
+ b = buf;
+ c = len;
+ ic = io->ilen; // how many bytes we've read and not flushed
+
+ while(c > 0){
+ n = -ic;
+ if(n > c)
+ n = c;
+ if(n == 0){
+ /* only continue if we are a file reader */
+ if(io->state != io·BufRdr)
+ break;
+
+ /* get more bytes */
+ if(sys·read(io->fd, io->cap, io->b, &nr)){
+ io->state = io·BufNil;
+ break;
+ }
+
+ if(nr == 0){
+ io->state = io·BufEnd;
+ break;
+ }
+
+ /* shift bytes within buffer so they end at terminal */
+ io->g = io->b;
+ io->pos += nr;
+ if(nr < io->cap){
+ io->g = io->e-nr;
+ mem·move(io->g, io->b, nr);
+ }
+ ic -= nr;
+ continue;
+ }
+ /* move our read bytes into the caller's buffer */
+ mem·move(b, io->e+ic, n);
+ c -= n;
+ ic += n;
+ b += n;
+ }
+ io->ilen = ic;
+ if(c == len && io->state == io·BufNil)
+ return -1;
+
+ return len-c;
}