From a0687e29e00c5e0389c7ed65415edca5e2a0dd75 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Tue, 9 Sep 2014 14:46:56 +0900 Subject: [PATCH] update xfile --- include/picrin/xfile.h | 522 ++++++++++++++++++++++++++++++++++++++--- xfile.c | 445 ----------------------------------- 2 files changed, 492 insertions(+), 475 deletions(-) delete mode 100644 xfile.c diff --git a/include/picrin/xfile.h b/include/picrin/xfile.h index 86fcb458..9d814bdc 100644 --- a/include/picrin/xfile.h +++ b/include/picrin/xfile.h @@ -8,6 +8,8 @@ extern "C" { #include #include #include +#include +#include typedef struct { int ungot; @@ -24,52 +26,512 @@ typedef struct { } xFILE; /* generic file constructor */ -xFILE *xfunopen(void *cookie, int (*read)(void *, char *, int), int (*write)(void *, const char *, int), long (*seek)(void *, long, int), int (*flush)(void *), int (*close)(void *)); +static inline xFILE *xfunopen(void *cookie, int (*read)(void *, char *, int), int (*write)(void *, const char *, int), long (*seek)(void *, long, int), int (*flush)(void *), int (*close)(void *)); /* resource aquisition */ -xFILE *xfopen(const char *, const char *); -xFILE *xfpopen(FILE *); -xFILE *xmopen(); -int xfclose(xFILE *); +static inline xFILE *xfpopen(FILE *); +static inline xFILE *xmopen(); +static inline xFILE *xfopen(const char *, const char *); +static inline int xfclose(xFILE *); /* buffer management */ -int xfflush(xFILE *); +static inline int xfflush(xFILE *); /* direct IO with buffering */ -size_t xfread(void *, size_t, size_t, xFILE *); -size_t xfwrite(const void *, size_t, size_t, xFILE *); +static inline size_t xfread(void *, size_t, size_t, xFILE *); +static inline size_t xfwrite(const void *, size_t, size_t, xFILE *); /* indicator positioning */ -long xfseek(xFILE *, long offset, int whence); -long xftell(xFILE *); -void xrewind(xFILE *); +static inline long xfseek(xFILE *, long offset, int whence); +static inline long xftell(xFILE *); +static inline void xrewind(xFILE *); /* stream status */ -void xclearerr(xFILE *); -int xfeof(xFILE *); -int xferror(xFILE *); +static inline void xclearerr(xFILE *); +static inline int xfeof(xFILE *); +static inline int xferror(xFILE *); /* character IO */ -int xfgetc(xFILE *); -char *xfgets(char *, int, xFILE *); -int xfputc(int, xFILE *); -int xfputs(const char *, xFILE *); -char xgetc(xFILE *); -int xgetchar(void); -int xputc(int, xFILE *); -int xputchar(int); -int xputs(char *); -int xungetc(int, xFILE *); +static inline int xfgetc(xFILE *); +static inline char *xfgets(char *, int, xFILE *); +static inline int xfputc(int, xFILE *); +static inline int xfputs(const char *, xFILE *); +static inline char xgetc(xFILE *); +static inline int xgetchar(void); +static inline int xputc(int, xFILE *); +static inline int xputchar(int); +static inline int xputs(char *); +static inline int xungetc(int, xFILE *); /* formatted I/O */ -int xprintf(const char *, ...); -int xfprintf(xFILE *, const char *, ...); -int xvfprintf(xFILE *, const char *, va_list); +static inline int xprintf(const char *, ...); +static inline int xfprintf(xFILE *, const char *, ...); +static inline int xvfprintf(xFILE *, const char *, va_list); /* standard I/O */ -extern xFILE *xstdin; -extern xFILE *xstdout; -extern xFILE *xstderr; +#define xstdin (xstdin__()) +#define xstdout (xstdout__()) +#define xstderr (xstderr__()) + + +/* private */ + +#define XF_EOF 1 +#define XF_ERR 2 + +static inline xFILE * +xfunopen(void *cookie, int (*read)(void *, char *, int), int (*write)(void *, const char *, int), long (*seek)(void *, long, int), int (*flush)(void *), int (*close)(void *)) +{ + xFILE *file; + + file = (xFILE *)malloc(sizeof(xFILE)); + if (! file) { + return NULL; + } + file->ungot = -1; + file->flags = 0; + /* set vtable */ + file->vtable.cookie = cookie; + file->vtable.read = read; + file->vtable.write = write; + file->vtable.seek = seek; + file->vtable.flush = flush; + file->vtable.close = close; + + return file; +} + +/* + * Derieved xFILE Classes + */ + +static inline FILE * +xf_unpack(void *cookie) +{ + switch ((long)cookie) { + default: return cookie; + case 0: return stdin; + case 1: return stdout; + case -1: return stderr; + } +} + +static inline int +xf_file_read(void *cookie, char *ptr, int size) +{ + FILE *file = xf_unpack(cookie); + int r; + + r = fread(ptr, 1, size, file); + if (r < size && ferror(file)) { + return -1; + } + if (r == 0 && feof(file)) { + clearerr(file); + } + return r; +} + +static inline int +xf_file_write(void *cookie, const char *ptr, int size) +{ + FILE *file = xf_unpack(cookie); + int r; + + r = fwrite(ptr, 1, size, file); + if (r < size) { + return -1; + } + return r; +} + +static inline long +xf_file_seek(void *cookie, long pos, int whence) +{ + return fseek(xf_unpack(cookie), pos, whence); +} + +static inline int +xf_file_flush(void *cookie) +{ + return fflush(xf_unpack(cookie)); +} + +static inline int +xf_file_close(void *cookie) +{ + return fclose(xf_unpack(cookie)); +} + +static inline xFILE * +xfpopen(FILE *fp) +{ + xFILE *file; + + file = xfunopen(fp, xf_file_read, xf_file_write, xf_file_seek, xf_file_flush, xf_file_close); + if (! file) { + return NULL; + } + + return file; +} + +#define XF_FILE_VTABLE xf_file_read, xf_file_write, xf_file_seek, xf_file_flush, xf_file_close + +static inline xFILE * +xstdin__() +{ + static xFILE xfile_stdin = { -1, 0, { (void *)0, XF_FILE_VTABLE } }; + + return &xfile_stdin; +} + +static inline xFILE * +xstdout__() +{ + static xFILE xfile_stdout = { -1, 0, { (void *)1, XF_FILE_VTABLE } }; + + return &xfile_stdout; +} + +static inline xFILE * +xstderr__() +{ + static xFILE xfile_stderr = { -1, 0, { (void *)-1, XF_FILE_VTABLE } }; + + return &xfile_stderr; +} + +struct xf_membuf { + char *buf; + long pos, end, capa; +}; + +static inline int +xf_mem_read(void *cookie, char *ptr, int size) +{ + struct xf_membuf *mem; + + mem = (struct xf_membuf *)cookie; + + if (size > mem->end - mem->pos) + size = mem->end - mem->pos; + memcpy(ptr, mem->buf + mem->pos, size); + mem->pos += size; + return size; +} + +static inline int +xf_mem_write(void *cookie, const char *ptr, int size) +{ + struct xf_membuf *mem; + + mem = (struct xf_membuf *)cookie; + + if (mem->pos + size >= mem->capa) { + mem->capa = (mem->pos + size) * 2; + mem->buf = realloc(mem->buf, mem->capa); + } + memcpy(mem->buf + mem->pos, ptr, size); + mem->pos += size; + if (mem->end < mem->pos) + mem->end = mem->pos; + return size; +} + +static inline long +xf_mem_seek(void *cookie, long pos, int whence) +{ + struct xf_membuf *mem; + + mem = (struct xf_membuf *)cookie; + + switch (whence) { + case SEEK_SET: + mem->pos = pos; + break; + case SEEK_CUR: + mem->pos += pos; + break; + case SEEK_END: + mem->pos = mem->end + pos; + break; + } + + return mem->pos; +} + +static inline int +xf_mem_flush(void *cookie) +{ + (void)cookie; + + return 0; +} + +static inline int +xf_mem_close(void *cookie) +{ + struct xf_membuf *mem; + + mem = (struct xf_membuf *)cookie; + free(mem->buf); + free(mem); + return 0; +} + +static inline xFILE * +xmopen() +{ + struct xf_membuf *mem; + + mem = (struct xf_membuf *)malloc(sizeof(struct xf_membuf)); + mem->buf = (char *)malloc(BUFSIZ); + mem->pos = 0; + mem->end = 0; + mem->capa = BUFSIZ; + + return xfunopen(mem, xf_mem_read, xf_mem_write, xf_mem_seek, xf_mem_flush, xf_mem_close); +} + +#undef XF_FILE_VTABLE + +static inline xFILE * +xfopen(const char *filename, const char *mode) +{ + FILE *fp; + xFILE *file; + + fp = fopen(filename, mode); + if (! fp) { + return NULL; + } + + file = xfpopen(fp); + if (! file) { + return NULL; + } + + return file; +} + +static inline int +xfclose(xFILE *file) +{ + int r; + + r = file->vtable.close(file->vtable.cookie); + if (r == EOF) { + return -1; + } + + free(file); + return 0; +} + +static inline int +xfflush(xFILE *file) +{ + return file->vtable.flush(file->vtable.cookie); +} + +static inline size_t +xfread(void *ptr, size_t block, size_t nitems, xFILE *file) +{ + char *dst = (char *)ptr; + char buf[block]; + size_t i, offset; + int n; + + for (i = 0; i < nitems; ++i) { + offset = 0; + if (file->ungot != -1 && block > 0) { + buf[0] = file->ungot; + offset += 1; + file->ungot = -1; + } + while (offset < block) { + n = file->vtable.read(file->vtable.cookie, buf + offset, block - offset); + if (n < 0) { + file->flags |= XF_ERR; + goto exit; + } + if (n == 0) { + file->flags |= XF_EOF; + goto exit; + } + offset += n; + } + memcpy(dst, buf, block); + dst += block; + } + + exit: + return i; +} + +static inline size_t +xfwrite(const void *ptr, size_t block, size_t nitems, xFILE *file) +{ + char *dst = (char *)ptr; + size_t i, offset; + int n; + + for (i = 0; i < nitems; ++i) { + offset = 0; + while (offset < block) { + n = file->vtable.write(file->vtable.cookie, dst + offset, block - offset); + if (n < 0) { + file->flags |= XF_ERR; + goto exit; + } + offset += n; + } + dst += block; + } + + exit: + return i; +} + +static inline long +xfseek(xFILE *file, long offset, int whence) +{ + file->ungot = -1; + return file->vtable.seek(file->vtable.cookie, offset, whence); +} + +static inline long +xftell(xFILE *file) +{ + return xfseek(file, 0, SEEK_CUR); +} + +static inline void +xrewind(xFILE *file) +{ + xfseek(file, 0, SEEK_SET); +} + +static inline void +xclearerr(xFILE *file) +{ + file->flags = 0; +} + +static inline int +xfeof(xFILE *file) +{ + return file->flags & XF_EOF; +} + +static inline int +xferror(xFILE *file) +{ + return file->flags & XF_ERR; +} + +static inline int +xfgetc(xFILE *file) +{ + char buf[1]; + + xfread(buf, 1, 1, file); + + if (xfeof(file)) { + return EOF; + } + + return buf[0]; +} + +static inline int +xungetc(int c, xFILE *file) +{ + file->ungot = c; + if (c != EOF) { + file->flags &= ~XF_EOF; + } + return c; +} + +static inline int +xgetchar(void) +{ + return xfgetc(xstdin); +} + +static inline int +xfputc(int c, xFILE *file) +{ + char buf[1]; + + buf[0] = c; + xfwrite(buf, 1, 1, file); + + return buf[0]; +} + +static inline int +xputchar(int c) +{ + return xfputc(c, xstdout); +} + +static inline int +xfputs(const char *str, xFILE *file) +{ + int len; + + len = strlen(str); + xfwrite(str, len, 1, file); + + return 0; +} + +static inline int +xprintf(const char *fmt, ...) +{ + va_list ap; + int n; + + va_start(ap, fmt); + n = xvfprintf(xstdout, fmt, ap); + va_end(ap); + return n; +} + +static inline int +xfprintf(xFILE *stream, const char *fmt, ...) +{ + va_list ap; + int n; + + va_start(ap, fmt); + n = xvfprintf(stream, fmt, ap); + va_end(ap); + return n; +} + +static inline int +xvfprintf(xFILE *stream, const char *fmt, va_list ap) +{ + va_list ap2; + + va_copy(ap2, ap); + { + char buf[vsnprintf(NULL, 0, fmt, ap2)]; + + vsnprintf(buf, sizeof buf + 1, fmt, ap); + + if (xfwrite(buf, sizeof buf, 1, stream) < 1) { + return -1; + } + + va_end(ap2); + return sizeof buf; + } +} #if defined(__cplusplus) } diff --git a/xfile.c b/xfile.c deleted file mode 100644 index 60d47a8a..00000000 --- a/xfile.c +++ /dev/null @@ -1,445 +0,0 @@ -#include "picrin/xfile.h" - -#include -#include -#include - -#define min(a,b) (((a)>(b))?(b):(a)) -#define max(a,b) (((a)<(b))?(b):(a)) - -#define XF_EOF 1 -#define XF_ERR 2 - -xFILE * -xfunopen(void *cookie, int (*read)(void *, char *, int), int (*write)(void *, const char *, int), long (*seek)(void *, long, int), int (*flush)(void *), int (*close)(void *)) -{ - xFILE *file; - - file = (xFILE *)malloc(sizeof(xFILE)); - if (! file) { - return NULL; - } - file->ungot = -1; - file->flags = 0; - /* set vtable */ - file->vtable.cookie = cookie; - file->vtable.read = read; - file->vtable.write = write; - file->vtable.seek = seek; - file->vtable.flush = flush; - file->vtable.close = close; - - return file; -} - -xFILE * -xfopen(const char *filename, const char *mode) -{ - FILE *fp; - xFILE *file; - - fp = fopen(filename, mode); - if (! fp) { - return NULL; - } - - file = xfpopen(fp); - if (! file) { - return NULL; - } - - return file; -} - -int -xfclose(xFILE *file) -{ - int r; - - r = file->vtable.close(file->vtable.cookie); - if (r == EOF) { - return -1; - } - - free(file); - return 0; -} - -int -xfflush(xFILE *file) -{ - return file->vtable.flush(file->vtable.cookie); -} - -size_t -xfread(void *ptr, size_t block, size_t nitems, xFILE *file) -{ - char *dst = (char *)ptr; - char buf[block]; - size_t i, offset; - int n; - - for (i = 0; i < nitems; ++i) { - offset = 0; - if (file->ungot != -1 && block > 0) { - buf[0] = file->ungot; - offset += 1; - file->ungot = -1; - } - while (offset < block) { - n = file->vtable.read(file->vtable.cookie, buf + offset, block - offset); - if (n < 0) { - file->flags |= XF_ERR; - goto exit; - } - if (n == 0) { - file->flags |= XF_EOF; - goto exit; - } - offset += n; - } - memcpy(dst, buf, block); - dst += block; - } - - exit: - return i; -} - -size_t -xfwrite(const void *ptr, size_t block, size_t nitems, xFILE *file) -{ - char *dst = (char *)ptr; - size_t i, offset; - int n; - - for (i = 0; i < nitems; ++i) { - offset = 0; - while (offset < block) { - n = file->vtable.write(file->vtable.cookie, dst + offset, block - offset); - if (n < 0) { - file->flags |= XF_ERR; - goto exit; - } - offset += n; - } - dst += block; - } - - exit: - return i; -} - -long -xfseek(xFILE *file, long offset, int whence) -{ - file->ungot = -1; - return file->vtable.seek(file->vtable.cookie, offset, whence); -} - -long -xftell(xFILE *file) -{ - return xfseek(file, 0, SEEK_CUR); -} - -void -xrewind(xFILE *file) -{ - xfseek(file, 0, SEEK_SET); -} - -void -xclearerr(xFILE *file) -{ - file->flags = 0; -} - -int -xfeof(xFILE *file) -{ - return file->flags & XF_EOF; -} - -int -xferror(xFILE *file) -{ - return file->flags & XF_ERR; -} - -int -xfgetc(xFILE *file) -{ - char buf[1]; - - xfread(buf, 1, 1, file); - - if (xfeof(file)) { - return EOF; - } - - return buf[0]; -} - -int -xungetc(int c, xFILE *file) -{ - file->ungot = c; - if (c != EOF) { - file->flags &= ~XF_EOF; - } - return c; -} - -int -xgetchar(void) -{ - return xfgetc(xstdin); -} - -int -xfputc(int c, xFILE *file) -{ - char buf[1]; - - buf[0] = c; - xfwrite(buf, 1, 1, file); - - return buf[0]; -} - -int -xputchar(int c) -{ - return xfputc(c, xstdout); -} - -int -xfputs(const char *str, xFILE *file) -{ - int len; - - len = strlen(str); - xfwrite(str, len, 1, file); - - return 0; -} - -int -xprintf(const char *fmt, ...) -{ - va_list ap; - int n; - - va_start(ap, fmt); - n = xvfprintf(xstdout, fmt, ap); - va_end(ap); - return n; -} - -int -xfprintf(xFILE *stream, const char *fmt, ...) -{ - va_list ap; - int n; - - va_start(ap, fmt); - n = xvfprintf(stream, fmt, ap); - va_end(ap); - return n; -} - -int -xvfprintf(xFILE *stream, const char *fmt, va_list ap) -{ - va_list ap2; - - va_copy(ap2, ap); - { - char buf[vsnprintf(NULL, 0, fmt, ap2)]; - - vsnprintf(buf, sizeof buf + 1, fmt, ap); - - if (xfwrite(buf, sizeof buf, 1, stream) < 1) { - return -1; - } - - va_end(ap2); - return sizeof buf; - } -} - -/* - * Derieved xFILE Classes - */ - -static FILE * -unpack(void *cookie) -{ - switch ((long)cookie) { - default: return cookie; - case 0: return stdin; - case 1: return stdout; - case -1: return stderr; - } -} - -static int -file_read(void *cookie, char *ptr, int size) -{ - FILE *file = unpack(cookie); - int r; - - r = fread(ptr, 1, size, file); - if (r < size && ferror(file)) { - return -1; - } - if (r == 0 && feof(file)) { - clearerr(file); - } - return r; -} - -static int -file_write(void *cookie, const char *ptr, int size) -{ - FILE *file = unpack(cookie); - int r; - - r = fwrite(ptr, 1, size, file); - if (r < size) { - return -1; - } - return r; -} - -static long -file_seek(void *cookie, long pos, int whence) -{ - return fseek(unpack(cookie), pos, whence); -} - -static int -file_flush(void *cookie) -{ - return fflush(unpack(cookie)); -} - -static int -file_close(void *cookie) -{ - return fclose(unpack(cookie)); -} - -xFILE * -xfpopen(FILE *fp) -{ - xFILE *file; - - file = xfunopen(fp, file_read, file_write, file_seek, file_flush, file_close); - if (! file) { - return NULL; - } - - return file; -} - -#define FILE_VTABLE file_read, file_write, file_seek, file_flush, file_close - -static xFILE xfile_stdin = { -1, 0, { (void *)0, FILE_VTABLE } }; -static xFILE xfile_stdout = { -1, 0, { (void *)1, FILE_VTABLE } }; -static xFILE xfile_stderr = { -1, 0, { (void *)-1, FILE_VTABLE } }; - -xFILE *xstdin = &xfile_stdin; -xFILE *xstdout = &xfile_stdout; -xFILE *xstderr = &xfile_stderr; - -struct membuf { - char *buf; - long pos, end, capa; -}; - -static int -mem_read(void *cookie, char *ptr, int size) -{ - struct membuf *mem; - - mem = (struct membuf *)cookie; - - size = min(size, mem->end - mem->pos); - memcpy(ptr, mem->buf + mem->pos, size); - mem->pos += size; - return size; -} - -static int -mem_write(void *cookie, const char *ptr, int size) -{ - struct membuf *mem; - - mem = (struct membuf *)cookie; - - if (mem->pos + size >= mem->capa) { - mem->capa = (mem->pos + size) * 2; - mem->buf = realloc(mem->buf, mem->capa); - } - memcpy(mem->buf + mem->pos, ptr, size); - mem->pos += size; - mem->end = max(mem->pos, mem->end); - return size; -} - -static long -mem_seek(void *cookie, long pos, int whence) -{ - struct membuf *mem; - - mem = (struct membuf *)cookie; - - switch (whence) { - case SEEK_SET: - mem->pos = pos; - break; - case SEEK_CUR: - mem->pos += pos; - break; - case SEEK_END: - mem->pos = mem->end + pos; - break; - } - - return mem->pos; -} - -static int -mem_flush(void *cookie) -{ - (void)cookie; - - return 0; -} - -static int -mem_close(void *cookie) -{ - struct membuf *mem; - - mem = (struct membuf *)cookie; - free(mem->buf); - free(mem); - return 0; -} - -xFILE * -xmopen() -{ - struct membuf *mem; - - mem = (struct membuf *)malloc(sizeof(struct membuf)); - mem->buf = (char *)malloc(BUFSIZ); - mem->pos = 0; - mem->end = 0; - mem->capa = BUFSIZ; - - return xfunopen(mem, mem_read, mem_write, mem_seek, mem_flush, mem_close); -}