diff --git a/include/picrin/port.h b/include/picrin/port.h index 32550231..dd5b8ae0 100644 --- a/include/picrin/port.h +++ b/include/picrin/port.h @@ -47,6 +47,7 @@ struct pic_port *pic_stderr(pic_state *); int pic_setvbuf(pic_file *, char *, int, size_t); int pic_fflush(pic_file *); +int pic_ffill(pic_file *); pic_file *pic_funopen(void *cookie, int (*read)(void *, char *, int), int (*write)(void *, const char *, int), fpos_t (*seek)(void *, fpos_t, int), int (*close)(void *)); diff --git a/src/port.c b/src/port.c index c62d9252..b6f4845c 100644 --- a/src/port.c +++ b/src/port.c @@ -71,6 +71,12 @@ pic_fflush(pic_file *file) return file->vtable.write(file->vtable.cookie, file->s, file->c - file->s); } +int +pic_ffill(pic_file *file) +{ + return file->vtable.read(file->vtable.cookie, file->c, file->e - file->c); +} + pic_file * pic_funopen(void *cookie, int (*read)(void *, char *, int), @@ -149,6 +155,34 @@ pic_fclose(pic_file *file) return 0; } +size_t +pic_fread(void *ptr, size_t block, size_t nitems, pic_file *file) +{ + int size, avail; + char *dst = (char *)ptr; + + size = block * nitems; /* TODO: optimize block read */ + + while (1) { + avail = file->c - file->s; + if (size <= avail) { + memcpy(dst, file->s, size); + file->c -= size; + memmove(file->s, file->c, avail - size); + break; + } + else { + memcpy(dst, file->s, avail); + file->c -= avail; + size -= avail; + dst += avail; + pic_ffill(file); + } + } + + return block * nitems; +} + size_t pic_fwrite(const void *ptr, size_t block, size_t nitems, pic_file *file) {