aboutsummaryrefslogtreecommitdiff
path: root/src/base/io/getc.c
blob: 68e1772e21ba83b27a1ade366c7eb6c7b4d33846 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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;
}