aboutsummaryrefslogtreecommitdiff
path: root/src/base/bufio/read.c
blob: ad0275c9c6c86f7e261fb3d899e8dcb342cc1ce7 (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
46
47
48
49
50
51
52
53
54
#include "internal.h"

intptr
bio·read(io·Header *io, intptr len, void *buf)
{
    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;
}