diff options
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/bufio/flush.c | 36 | ||||
-rw-r--r-- | src/base/bufio/getc.c | 45 | ||||
-rw-r--r-- | src/base/bufio/getr.c | 29 | ||||
-rw-r--r-- | src/base/bufio/init.c | 102 | ||||
-rw-r--r-- | src/base/bufio/offset.c | 24 | ||||
-rw-r--r-- | src/base/bufio/open.c | 27 | ||||
-rw-r--r-- | src/base/bufio/openfd.c | 12 | ||||
-rw-r--r-- | src/base/bufio/print.c | 14 | ||||
-rw-r--r-- | src/base/bufio/putc.c | 19 | ||||
-rw-r--r-- | src/base/bufio/read.c | 54 | ||||
-rw-r--r-- | src/base/bufio/readuntil.c | 64 | ||||
-rw-r--r-- | src/base/bufio/rules.mk | 22 | ||||
-rw-r--r-- | src/base/bufio/seek.c | 57 | ||||
-rw-r--r-- | src/base/bufio/ungetc.c | 13 | ||||
-rw-r--r-- | src/base/bufio/ungetr.c | 13 | ||||
-rw-r--r-- | src/base/bufio/vprint.c | 34 | ||||
-rw-r--r-- | src/base/bufio/write.c | 40 | ||||
-rw-r--r-- | src/base/fmt/do.c | 2 | ||||
-rw-r--r-- | src/base/mem/arena.c | 9 | ||||
-rw-r--r-- | src/base/mem/copy.c | 14 | ||||
-rw-r--r-- | src/base/mem/findc.c | 14 | ||||
-rw-r--r-- | src/base/mem/move.c | 22 | ||||
-rw-r--r-- | src/base/mem/rules.mk | 3 | ||||
-rw-r--r-- | src/base/mem/set.c | 12 | ||||
-rw-r--r-- | src/base/mem/set64.c | 4 | ||||
-rw-r--r-- | src/base/utf/canfit.c | 3 |
26 files changed, 673 insertions, 15 deletions
diff --git a/src/base/bufio/flush.c b/src/base/bufio/flush.c new file mode 100644 index 0000000..0974766 --- /dev/null +++ b/src/base/bufio/flush.c @@ -0,0 +1,36 @@ +#include "internal.h" + +int +bio·flush(io·Header *io) +{ + intptr ni, no; + + switch(io->state){ + case io·BufWtr: + if((ni = io->cap + io->olen)) + return 0; + + sys·write(io->fd, ni, io->b, &no); + + if(no!=ni){ + io->pos += ni; + io->olen = -io->cap; + return 0; + } + + io->state = io·BufNil; + io->olen = 0; + break; + + case io·BufEof: + io->state = io·BufRdr; + /* fallthrough */ + case io·BufRdr: + io->ilen = 0; + io->g = io->e; + return 0; + default: + ; + } + return io·BufEof; +} 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; +} diff --git a/src/base/bufio/getr.c b/src/base/bufio/getr.c new file mode 100644 index 0000000..579a387 --- /dev/null +++ b/src/base/bufio/getr.c @@ -0,0 +1,29 @@ +#include "internal.h" + +rune +bio·getr(io·Header *io) +{ + int c, i; + rune r; + char buf[UTFmax]; + + c = bio·getc(io); + if(utf8·onebyte(c)){ + io->runesz = 1; + return c; + } + buf[0] = c; + + for(i=1;;){ + if((c = bio·getc(io))<0) + return c; + + buf[i++] = c; + if(utf8·fullrune(buf, i)){ + io->runesz = utf8·decode(buf, &r); + while(i-- > io->runesz) + bio·ungetc(io); + return r; + } + } +} diff --git a/src/base/bufio/init.c b/src/base/bufio/init.c new file mode 100644 index 0000000..7e6dcee --- /dev/null +++ b/src/base/bufio/init.c @@ -0,0 +1,102 @@ +#include "internal.h" + +#define MAXHEADERS 20 +static io·Header *tracked[MAXHEADERS]; +static int doexit; + +static void +untrackall(void *arg) +{ + int i; + io·Header *it; + + for(i=0; i < MAXHEADERS; i++){ + it = tracked[i]; + if(it){ + tracked[i] = nil; + bio·flush(it); + } + } +} + +static void +untrack(io·Header *io) +{ + int i; + + for(i=0; i<arrlen(tracked); i++){ + if(tracked[i] == io) + tracked[i] = nil; + } +} + +static void +track(io·Header *io) +{ + int i; + + untrack(io); + for(i=0; i<arrlen(tracked); i++){ + if(!tracked[i]){ + tracked[i] = io; + break; + } + } + + if(!doexit){ + doexit = 1; + rt·atexit(untrackall, nil); + } +} + +int +bio·initcap(io·Header *io, int fd, int mode, int cap, uchar *buf) +{ + buf += io·BufUngets; + cap += io·BufUngets; + + switch(mode & ~(sys·OCloseExec|sys·OTrunc)){ + default: + fmt·fprint(2, "initcap: unknown mode %d\n" , mode); + return io·BufErr; + case sys·ORead: + io->state = io·BufRdr; + io->olen = 0; + break; + case sys·OWrite: + track(io); + io->state = io·BufWtr; + io->olen = -cap; + break; + } + + io->b = buf; + io->e = buf+cap; + io->g = io->e; + io->fd = fd; + io->cap = cap; + io->pos = io->runesz = io->flag = io->ilen = io->line = 0; + return 0; +} + +int +bio·init(io·Buffer *io, int fd, int mode) +{ + return bio·initcap(header(io), fd, mode, io·BufLen + io·BufUngets, io->b); +} + +int +bio·close(io·Header *io) +{ + int err; + + untrack(io); + + err = bio·flush(io); + if(io->flag == io·BufMagic){ + io->flag = 0; + if((err=sys·close(io->fd))) + return err; + } + return 0; +} diff --git a/src/base/bufio/offset.c b/src/base/bufio/offset.c new file mode 100644 index 0000000..15579c4 --- /dev/null +++ b/src/base/bufio/offset.c @@ -0,0 +1,24 @@ +#include "internal.h" + +intptr +bio·offset(io·Header *io) +{ + intptr n; + switch(io->state){ + default: + fmt·fprint(2, "offset: unknown state %d\n", io->state); + n = io·BufEof; + break; + + case io·BufEnd: + case io·BufRdr: + n = io->pos + io->ilen; + break; + + case io·BufWtr: + n = io->pos + (io->cap + io->olen); + break; + } + + return n; +} diff --git a/src/base/bufio/open.c b/src/base/bufio/open.c new file mode 100644 index 0000000..29ccae1 --- /dev/null +++ b/src/base/bufio/open.c @@ -0,0 +1,27 @@ +#include "internal.h" + +int +bio·open(char *path, int flag, io·Buffer *io) +{ + int fd; + switch(flag & ~(sys·OCloseExec|sys·OTrunc)){ + default: + fmt·fprint(2, "open: unknown flag %d\n", flag); + return 1; + + case sys·ORead: + if(sys·open(path, flag, 0, &fd)) + return 1; + break; + + case sys·OWrite: + if(sys·open(path, flag, 0666, &fd)) + return 1; + break; + } + if(bio·openfd(fd, flag, io)){ + sys·close(fd); + return 1; + } + return 0; +} diff --git a/src/base/bufio/openfd.c b/src/base/bufio/openfd.c new file mode 100644 index 0000000..66ca967 --- /dev/null +++ b/src/base/bufio/openfd.c @@ -0,0 +1,12 @@ +#include "internal.h" + +int +bio·openfd(int fd, int flag, io·Buffer *io) +{ + int err; + if((err=bio·init(io, fd, flag))) + return err; + + io->flag = io·BufMagic; + return 0; +} diff --git a/src/base/bufio/print.c b/src/base/bufio/print.c new file mode 100644 index 0000000..04a85f9 --- /dev/null +++ b/src/base/bufio/print.c @@ -0,0 +1,14 @@ +#include "internal.h" + +int +bio·print(io·Header *io, char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = bio·vprint(io, fmt, args); + va_end(args); + + return n; +} diff --git a/src/base/bufio/putc.c b/src/base/bufio/putc.c new file mode 100644 index 0000000..e91a1f1 --- /dev/null +++ b/src/base/bufio/putc.c @@ -0,0 +1,19 @@ +#include "internal.h" + +int +bio·putc(io·Header *io, int c) +{ + intptr i; + + for(;;){ + i = io->olen; + if(i){ + io->e[i++] = c; + io->olen = i; + return 0; + } + if(bio·flush(io) == io·BufEof) + break; + } + return io·BufEof; +} diff --git a/src/base/bufio/read.c b/src/base/bufio/read.c new file mode 100644 index 0000000..ad0275c --- /dev/null +++ b/src/base/bufio/read.c @@ -0,0 +1,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; +} diff --git a/src/base/bufio/readuntil.c b/src/base/bufio/readuntil.c new file mode 100644 index 0000000..8084cca --- /dev/null +++ b/src/base/bufio/readuntil.c @@ -0,0 +1,64 @@ +#include "internal.h" + +void * +bio·readuntil(io·Header *io, int delim) +{ + char *b, *e; + intptr i, j; + + i = -io->ilen; + if(i==0){ + if(io->state != io·BufRdr){ + if(io->state == io·BufEnd) + io->state = io·BufRdr; + io->line = 0; + io->g = io->e; + return nil; + } + } + + /* best case, we find it in the remaining bytes */ + b = (char*)io->e - i; + if((e = mem·findc(b, i, delim)) != nil){ + j = (e - b)+1; + io->line = j; + io->ilen += j; + return b; + } + /* ok no luck, shift over the data and get more */ + if(i < io->cap) + mem·move(io->b, b, i); + io->g = io->b; + /* write to the buffer while we search for delim */ + b = (char *)io->b + i; + while(i < io->cap){ + if(sys·read(io->fd, io->cap-i, b, &j)){ + mem·move(io->e-i, io->b, i); + io->line = +i; + io->ilen = -i; + io->g = io->e - i; + return 0; + } + io->pos += j; + i += j; + e = mem·findc(b, j, delim); + if(e!=nil){ + /* finally have a hit. reset the world */ + b = (char*)io->e - i; + if(i < io->cap){ + mem·move(b, io->b, i); + io->g = (uchar *)b; + } + j = (e - (char*)io->b) + 1; + io->line = j; + io->ilen = j - i; + return b; + } + b += j; + } + + io->line = +io->cap; + io->ilen = -io->cap; + io->g = io->b; + return 0; +} diff --git a/src/base/bufio/rules.mk b/src/base/bufio/rules.mk index 8089e77..4546aeb 100644 --- a/src/base/bufio/rules.mk +++ b/src/base/bufio/rules.mk @@ -1,5 +1,17 @@ -# SRCS_$(d)+=\ -# $(d)/bufio/get.c\ -# $(d)/bufio/read.c\ -# $(d)/bufio/reader.c\ -# $(d)/bufio/unget.c\ +SRCS_$(d)+=\ + $(d)/bufio/flush.c\ + $(d)/bufio/getc.c\ + $(d)/bufio/getr.c\ + $(d)/bufio/init.c\ + $(d)/bufio/offset.c\ + $(d)/bufio/open.c\ + $(d)/bufio/openfd.c\ + $(d)/bufio/print.c\ + $(d)/bufio/putc.c\ + $(d)/bufio/read.c\ + $(d)/bufio/readuntil.c\ + $(d)/bufio/seek.c\ + $(d)/bufio/ungetc.c\ + $(d)/bufio/ungetr.c\ + $(d)/bufio/vprint.c\ + $(d)/bufio/write.c diff --git a/src/base/bufio/seek.c b/src/base/bufio/seek.c new file mode 100644 index 0000000..5d25173 --- /dev/null +++ b/src/base/bufio/seek.c @@ -0,0 +1,57 @@ +#include "internal.h" + +int +bio·seek(io·Header *io, intptr offset, int whence, intptr *pos) +{ + intptr n,d,cap; + + switch(io->state){ + default: + fmt·fprint(2, "seek: unknown state %d\n", io->state); + return io·BufEof; + case io·BufEnd: + io->state = io·BufRdr; + io->ilen = 0; + io->g = io->e; + /* fallthrough */ + case io·BufRdr: + n = offset; + if(whence == sys·SeekCur){ + n += bio·offset(io); + whence = sys·SeekSet; + } + + /* can we seek inside our buffer */ + if(whence == sys·SeekSet){ + d = n - bio·offset(io); + cap = io->e - io->g; + if(-cap <= d && d <= cap){ + io->ilen += d; + if(d >= 0){ + if(io->ilen <= 0){ + *pos = n; + return 0; + } + }else{ + if(io->e - io->g >= -io->ilen){ + *pos = n; + return 0; + } + } + } + } + + /* nope, call the kernel to do it for us */ + sys·seek(io->fd, offset, whence, &n); + io->ilen = 0; + io->g = io->e; + break; + + case io·BufWtr: + bio·flush(io); + sys·seek(io->fd, offset, whence, &n); + break; + } + io->pos = *pos = n; + return 0; +} diff --git a/src/base/bufio/ungetc.c b/src/base/bufio/ungetc.c new file mode 100644 index 0000000..70abbab --- /dev/null +++ b/src/base/bufio/ungetc.c @@ -0,0 +1,13 @@ +#include "internal.h" + +int +bio·ungetc(io·Header *io) +{ + if(io->state == io·BufEnd) + io->state = io·BufRdr; + if(io->state != io·BufRdr) + return io·BufEof; + + io->ilen--; + return 0; +} diff --git a/src/base/bufio/ungetr.c b/src/base/bufio/ungetr.c new file mode 100644 index 0000000..8abdc39 --- /dev/null +++ b/src/base/bufio/ungetr.c @@ -0,0 +1,13 @@ +#include "internal.h" + +rune +bio·ungetr(io·Header *io) +{ + if(io->state == io·BufEnd) + io->state = io·BufRdr; + if(io->state != io·BufRdr) + return io·BufEof; + io->ilen -= io->runesz; + io->runesz = 0; + return 0; +} diff --git a/src/base/bufio/vprint.c b/src/base/bufio/vprint.c new file mode 100644 index 0000000..70be6bf --- /dev/null +++ b/src/base/bufio/vprint.c @@ -0,0 +1,34 @@ +#include "internal.h" + +static int +flush(fmt·State *fmt) +{ + io·Header *io = fmt->file; + io->olen = fmt->buffer.cur - fmt->buffer.end; + if(bio·flush(io)) + return 0; + + fmt->buffer.end = (char*)io->e; + fmt->buffer.cur = fmt->buffer.beg = fmt->buffer.end + io->olen; + return 1; +} + +int +bio·vprint(io·Header *io, char *fmt, va_list args) +{ + int n; + fmt·State f; + + f.buffer.end = (char*)io->e; + f.buffer.beg = f.buffer.cur = (char*)(io->e + io->olen); + f.n = 0; + f.file = io; + f.flush = flush; + + va_copy(f.args,args); + n = fmt·do(&f, fmt); + va_end(f.args); + + io->olen = f.buffer.cur - f.buffer.beg; + return n; +} diff --git a/src/base/bufio/write.c b/src/base/bufio/write.c new file mode 100644 index 0000000..8b64055 --- /dev/null +++ b/src/base/bufio/write.c @@ -0,0 +1,40 @@ +#include "internal.h" + +intptr +bio·write(io·Header *io, intptr len, void *buf) +{ + char *b; + intptr c, o, nw, n; + + b = buf; + c = len; + o = io->olen; + + while(c > 0){ + n = -o; + if(n > c) + n = c; + if(n == 0){ + if(io->state != io·BufWtr) + return io·BufEof; + switch(sys·write(io->fd, io->cap, io->b, &nw)){ + case 0: + if(nw != io->cap) goto error; + io->pos += nw; + o = -io->cap; + continue; + case sys·ErrorInterrupt: + io->state = io·BufNil; + /* fallthrough */ + default: error: + return io·BufEof; + } + } + mem·move(io->e+o, b, n); + o += n; + c -= n; + b += n; + } + io->olen = o; + return len-c; +} diff --git a/src/base/fmt/do.c b/src/base/fmt/do.c index 71b005e..3825fc8 100644 --- a/src/base/fmt/do.c +++ b/src/base/fmt/do.c @@ -212,7 +212,7 @@ copy(fmt·State *io, char *m, int sz, int n) if(utf8·onebyte(r)){ nb=1; m++; - }else if((me-m) >= UTFmax || utf8·canfit(m, me-m)){ + }else if((me-m) >= UTFmax || utf8·fullrune(m, me-m)){ nb=utf8·decode(m, &r); m+=n; }else diff --git a/src/base/mem/arena.c b/src/base/mem/arena.c index b2ce044..37e7b56 100644 --- a/src/base/mem/arena.c +++ b/src/base/mem/arena.c @@ -25,15 +25,13 @@ struct mem·Arena struct Block first; }; -static -void* +static void* ·arenaalloc(void *heap, uint n, ulong size) { return mem·arenaalloc(heap, n, size); } -static -void +static void ·arenafree(void *heap, void *ptr) { /* no-op */ @@ -45,8 +43,7 @@ mem·Allocator mem·ArenaAllocator = { }; -static -void +static void grow(mem·Arena *a, vlong min) { uintptr size; diff --git a/src/base/mem/copy.c b/src/base/mem/copy.c new file mode 100644 index 0000000..5ce4f90 --- /dev/null +++ b/src/base/mem/copy.c @@ -0,0 +1,14 @@ +#include "internal.h" + +int +mem·copy(void *dst, void *src, uintptr len) +{ + char *d, *s; + if((long)len < 0) + return 1; + + d=dst, s=src; + while(len-- > 0) + *d++ = *s++; + return 0; +} diff --git a/src/base/mem/findc.c b/src/base/mem/findc.c new file mode 100644 index 0000000..d3215c5 --- /dev/null +++ b/src/base/mem/findc.c @@ -0,0 +1,14 @@ +#include "internal.h" + +void * +mem·findc(void *addr, uintptr len, int c) +{ + uchar *a = addr; + + c &= 0xFF; + while(len-- > 0){ + if(*a++ == c) + return a-1; + } + return nil; +} diff --git a/src/base/mem/move.c b/src/base/mem/move.c new file mode 100644 index 0000000..5ad4074 --- /dev/null +++ b/src/base/mem/move.c @@ -0,0 +1,22 @@ +#include "internal.h" + +int +mem·move(void *dst, void *src, uintptr len) +{ + char *d, *s; + if((long)len < 0) + return 1; + + d=dst, s=src; + if((s < d) && (s+len > d)) + goto aliased; + while(len-- > 0) + *d++ = *s++; + return 0; + +aliased: + d+=len, s+=len; + while(len-- > 0) + *--d = *--s; + return 0; +} diff --git a/src/base/mem/rules.mk b/src/base/mem/rules.mk index b912d0c..fda54e1 100644 --- a/src/base/mem/rules.mk +++ b/src/base/mem/rules.mk @@ -2,4 +2,7 @@ SRCS_$(d)+=\ $(d)/mem/arena.c\ $(d)/mem/buffer.c\ $(d)/mem/interface.c\ + $(d)/mem/set.c\ $(d)/mem/set64.c\ + $(d)/mem/copy.c\ + $(d)/mem/move.c diff --git a/src/base/mem/set.c b/src/base/mem/set.c new file mode 100644 index 0000000..2e296be --- /dev/null +++ b/src/base/mem/set.c @@ -0,0 +1,12 @@ +#include "internal.h" + +int +mem·set(void *addr, int c, uintptr len) +{ + char *a = addr; + + while(len-- > 0) + *a++ = c; + + return 0; +} diff --git a/src/base/mem/set64.c b/src/base/mem/set64.c index 464b3ad..7000866 100644 --- a/src/base/mem/set64.c +++ b/src/base/mem/set64.c @@ -1,6 +1,6 @@ #include "internal.h" -void +int mem·set64(void *dst, uint64 val, uintptr size) { intptr i; @@ -10,4 +10,6 @@ mem·set64(void *dst, uint64 val, uintptr size) for(; i < size; i++) ((byte*)dst)[i] = ((byte*)&val)[i&7]; + + return 0; } diff --git a/src/base/utf/canfit.c b/src/base/utf/canfit.c index 4579ab3..fddf580 100644 --- a/src/base/utf/canfit.c +++ b/src/base/utf/canfit.c @@ -2,7 +2,7 @@ /* returns 1 if string of length n is long enough to be decoded */ int -utf8·canfit(byte* s, int n) +utf8·fullrune(byte* s, int n) { int i; rune c; @@ -13,7 +13,6 @@ utf8·canfit(byte* s, int n) c = *(ubyte*)s; if(c < TByte1) return 1; - if(c < TByte3) return n >= 2; if(c < TByte4) |