diff options
Diffstat (limited to 'src/base/io/getc.c')
-rw-r--r-- | src/base/io/getc.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/base/io/getc.c b/src/base/io/getc.c new file mode 100644 index 0000000..68e1772 --- /dev/null +++ b/src/base/io/getc.c @@ -0,0 +1,45 @@ +#include "internal.h" + +int +io·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; +} |