From c5c92d9615cc8eea6181c82a4cf103fa22f64b13 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 29 May 2012 00:04:57 +0200 Subject: [PATCH] Added ungetc(3). --- libmaxsi/decl/FILE.h | 3 +++ libmaxsi/file.c | 24 +++++++++++++++++++++++- libmaxsi/include/stdio.h | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libmaxsi/decl/FILE.h b/libmaxsi/decl/FILE.h index 13d5ef83..ba6c5195 100644 --- a/libmaxsi/decl/FILE.h +++ b/libmaxsi/decl/FILE.h @@ -6,6 +6,7 @@ #define _FILE_LAST_WRITE (1<<2) #define _FILE_LAST_READ (1<<3) #define _FILE_AUTO_LOCK (1<<4) +#define _FILE_MAX_PUSHBACK 8 typedef struct _FILE { /* This is non-standard, but useful. If you allocate your own FILE and @@ -31,5 +32,7 @@ typedef struct _FILE struct _FILE* next; int flags; size_t bufferused; + size_t numpushedback; + unsigned char pushedback[_FILE_MAX_PUSHBACK]; } FILE; #endif diff --git a/libmaxsi/file.c b/libmaxsi/file.c index a13bc439..4307e5ac 100644 --- a/libmaxsi/file.c +++ b/libmaxsi/file.c @@ -52,6 +52,18 @@ void funregister(FILE* fp) size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp) { + if ( fp->numpushedback && size != 1 ) { errno = ENOSYS; return 0; } + if ( fp->numpushedback && nmemb ) + { + unsigned char* buf = (unsigned char*) ptr; + size_t amount = nmemb < fp->numpushedback ? nmemb : fp->numpushedback; + for ( size_t i = 0; i < amount; i++ ) + { + buf[i] = fp->pushedback[--(fp->numpushedback)]; + } + if ( nmemb <= amount ) { return nmemb; } + return amount + fread(buf + amount, size, nmemb - amount, fp); + } if ( !fp->read_func ) { errno = EBADF; return 0; } fp->flags &= ~_FILE_LAST_WRITE; fp->flags |= _FILE_LAST_READ; return fp->read_func(ptr, size, nmemb, fp->user); @@ -96,6 +108,7 @@ size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp) int fseeko(FILE* fp, off_t offset, int whence) { + fp->numpushedback = 0; return (fp->seek_func) ? fp->seek_func(fp->user, offset, whence) : 0; } @@ -122,6 +135,7 @@ int ferror(FILE* fp) int feof(FILE* fp) { + if ( fp->numpushedback ) { return 0; } if ( !fp->eof_func ) { return 0; } return fp->eof_func(fp->user); } @@ -135,7 +149,7 @@ void rewind(FILE* fp) off_t ftello(FILE* fp) { if ( !fp->tell_func ) { errno = EBADF; return -1; } - return fp->tell_func(fp->user); + return fp->tell_func(fp->user) - fp->numpushedback; } long ftell(FILE* fp) @@ -143,6 +157,14 @@ long ftell(FILE* fp) return (long) ftello(fp); } +int ungetc(int c, FILE* fp) +{ + if ( fp->numpushedback == _FILE_MAX_PUSHBACK ) { errno = ERANGE; return EOF; } + unsigned char uc = c; + fp->pushedback[fp->numpushedback++] = uc; + return uc; +} + int fflush(FILE* fp) { if ( !fp ) diff --git a/libmaxsi/include/stdio.h b/libmaxsi/include/stdio.h index 361e6e26..71e18188 100644 --- a/libmaxsi/include/stdio.h +++ b/libmaxsi/include/stdio.h @@ -107,6 +107,7 @@ extern char* sortix_gets(void); extern int sortix_puts(const char* str); extern int sprintf(char* restrict s, const char* restrict format, ...); extern int sscanf(const char* restrict s, const char* restrict format, ...); +extern int ungetc(int c, FILE* stream); extern int vfprintf(FILE* restrict stream, const char* restrict format, __gnuc_va_list ap); extern int vprintf(const char* restrict format, __gnuc_va_list ap); extern int vsnprintf(char* restrict, size_t, const char* restrict, __gnuc_va_list); @@ -134,7 +135,6 @@ extern int rename(const char* oldname, const char* newname); extern int renameat(int oldfd, const char* oldname, int newfd, const char* newname); extern int scanf(const char* restrict format, ...); extern int setvbuf(FILE* restrict stream, char* restrict buf, int type, size_t size); -extern int ungetc(int c, FILE* stream); extern int vdprintf(int fildes, const char* restrict format, __gnuc_va_list ap); extern int vfscanf(FILE* restrict stream, const char* restrict format, __gnuc_va_list arg); extern int vscanf(const char* restrict format, __gnuc_va_list arg);