#include #include #include #include #include #include #if 1 #define V4K_IMPLEMENTATION #include "/prj/v4k/engine/joint/v4k.h" #define vl tempvl #define test2 test2_ #else #define vl(fmt, list) fmt // @fixme static unsigned array_c; #define array(t) t* #define array_resize(arr, c) ( (arr) = vrealloc((arr), (c) * sizeof(0[arr])) ) #define array_push(arr, v) ( array_c = array_count(arr), array_c[(arr) = vrealloc((arr), (array_c + 1) * sizeof(0[arr]))] = (v) ) #define array_pop(arr) ( (arr) ? (arr) = vrealloc((arr), (array_count(arr)-1) * sizeof(0[arr])) : (0) ) #define array_count(arr) (int)( (arr) ? vlen(arr) / sizeof(0[arr]) : sizeof(0[arr]) - sizeof(0[arr]) ) #define array_free(arr) ( (arr) ? (vrealloc(arr, 0), 1) : 0 ) void* vrealloc( void* p, size_t sz ) { if( !sz ) { if( p ) { size_t *ret = (size_t*)p - 2; ret[0] = 0; ret[1] = 0; realloc( ret, 0 ); } return 0; } else { size_t *ret; if( !p ) { ret = (size_t*)realloc( 0, sizeof(size_t) * 2 + sz ); ret[0] = sz; ret[1] = 0; } else { ret = (size_t*)p - 2; size_t osz = ret[0]; size_t ocp = ret[1]; if( sz <= (osz + ocp) ) { ret[0] = sz; ret[1] = ocp - (sz - osz); } else { ret = (size_t*)realloc( ret, sizeof(size_t) * 2 + sz * 1.75 ); ret[0] = sz; ret[1] = (size_t)(sz * 1.75) - sz; } } return &ret[2]; } } size_t vlen( void* p ) { return p ? 0[ (size_t*)p - 2 ] : 0; } #endif typedef struct FILE2 { FILE *fp; int64_t pos; int errno_; array(char) arr; } FILE2; void *tmpfile2(void) { FILE2 *mem = (FILE2*)calloc(1, sizeof(FILE2)); mem->fp = tmpfile(); return mem; } void *fopen2(void *buf, const char *mode) { FILE2 *mem = (FILE2*)calloc(1, sizeof(FILE2)); if( mode[0] != 'm' && buf ) { mem->fp = fopen((const char *)buf, mode); } return (FILE*)mem; } int fclose2(void* handler) { FILE2 *mem = (FILE2*)handler; if( mem->arr ) { array_free(mem->arr); } if( mem->fp ) { fclose(mem->fp); } memset(mem, 0, sizeof(FILE2)); free(mem); return 0; } // r/w int fwrite2(const void *buf, int size, int count, void *handler) { FILE2 *mem = handler; if( mem->fp ) return fwrite(buf, size, count, mem->fp); size *= count; size_t available = array_count(mem->arr) - mem->pos; if( size > available ) { if( 1 ) { // if growthable array_resize(mem->arr, size - available); } else { size = available; } } memcpy(mem->arr, buf, size); mem->pos += size; return count; } int fread2(void *buf, int size, int count, void *handler) { FILE2 *mem = handler; if( mem->fp ) return fread(buf, size, count, mem->fp); size_t available = array_count(mem->arr) - mem->pos; size_t total = size * count; while( (total/size) > count ) { total -= size; } if( total > 0 ) { memcpy(buf, mem->arr, total); mem->pos += total; return total / size; } return 0; } // cursor int64_t ftello2(void *handler) { FILE2 *mem = handler; if( mem->fp ) return ftell(mem->fp); return mem->pos; } int64_t fseeko2(void *handler, int64_t offset, int whence) { FILE2 *mem = handler; if( mem->fp ) return fseek(mem->fp, offset, whence); /**/ if( whence == SEEK_SET ) mem->pos = offset; else if( whence == SEEK_CUR ) mem->pos += offset; else if( whence == SEEK_END ) mem->pos = array_count(mem->arr) + offset; // - 1 - offset; else return -1; if( mem->pos >= array_count(mem->arr) ) { return -1; } return mem->pos; // (fpos_t)mem->pos; } // buffering void setbuf2(void *handler, char *buffer) { FILE2 *mem = handler; if( mem->fp ) setbuf(mem->fp, buffer); } int setvbuf2(void *handler, char *buffer, int mode, size_t size) { FILE2 *mem = handler; if( mem->fp ) return setvbuf2(mem->fp, buffer, mode, size); return 0; } int fflush2(void *handler) { FILE2 *mem = handler; if( mem->fp ) return fflush(mem->fp); return 0; } int ungetc2(int ch, void *handler) { FILE2 *mem = handler; if( mem->fp ) return ungetc(ch, mem->fp); #if 0 // todo: pushes the uint8_t character onto the specified stream so that it's available for the next read operation. #endif return -1; } // internal array(char)* fdata(void *handler) { FILE2 *mem = handler; if( mem->fp ) return NULL; return &mem->arr; } #define FILE void #define tmpfile tmpfile2 #define fopen fopen2 #define ftello ftello2 #define ftell (int)ftello2 #define fgetpos fgetpos2 #define fseeko fseeko2 #define fseek (int)fseeko2 #define fsetpos fsetpos2 #define rewind rewind2 #define fread fread2 #define fgets fgets2 #define fgetc fgetc2 #define getc getc2 #define fwrite fwrite2 #define fputs fputs2 #define fputc fputc2 #define putc putc2 #define ferror ferror2 #define feof feof2 #define clearerr clearerr2 #define vfprintf vfprintf2 // @fixme: return type #define fprintf fprintf2 #define setbuf setbuf2 #define setvbuf setvbuf2 #define fflush fflush2 #define ungetc ungetc2 #define fclose fclose2 // not doing: #define freopen(filename,mode,handler) freopen(filename,mode, ((FILE2*)(handler))->fp ) #define freopen(filename,mode,handler) freopen(filename,mode, ((FILE2*)(handler))->fp ) #define fscanf(handler,format,...) fscanf(((FILE2*)(handler))->fp, format, __VA_ARGS__) // format // int fscanf(FILE *fp, const char *format, ...); int vfprintf(FILE *fp, const char *format, va_list args) { // @fixme: return type const char *str = vl(format, args); return fwrite(str, strlen(str), 1, fp) == 1; } int fprintf(FILE *fp, const char *fmt, ...) { va_list va; va_start(va, fmt); int rc = vfprintf(fp, fmt, va); va_end(va); return rc; } // error handling int feof(FILE *fp) { return ((FILE2*)fp)->errno_ == EOF; } int ferror(FILE *fp) { return ((FILE2*)fp)->errno_; } void clearerr(FILE *fp) { ((FILE2*)fp)->errno_ = 0; } // aliases int fgetpos(FILE *fp, fpos_t *pos) { return (*pos = ftell(fp)) != -1L; } int fsetpos(FILE *fp, const fpos_t *pos) { return fseek(fp, *pos, SEEK_SET); } void rewind(FILE *fp) { fseek(fp, 0L, SEEK_SET); } // aliases int fgetc(FILE *fp) { int ch = EOF; return fread(&ch, sizeof(char), 1, fp) != 1 ? EOF : ch; } int fputc(int ch, FILE *fp) { return fwrite(&ch, sizeof(char), 1, fp) == 1; } int getc(FILE *fp) { return fgetc(fp); } int putc(int ch, FILE *fp) { return fputc(ch, fp); } int fputs(const char *str, FILE *fp) { return fwrite(str, strlen(str), 1, fp) == 1 && fwrite("\n",1,1,fp) == 1; } char* fgets(char *str, int n, FILE *fp) { char *cpy = str; int ch = EOF; while( n && (ch = fgetc(fp)) != EOF && !strchr("\r\n", ch) ) *str++ = ch, --n; while( n && (ch = fgetc(fp)) != EOF && strchr("\r\n", ch) ) *str++ = ch, --n; return ch == EOF ? NULL : cpy; } #include void test1() { char buf[256] = {0}; FILE *fp = fopen(__FILE__,"rb"); assert(fp); assert(fgets(buf, sizeof(buf), fp)); assert(~puts(buf)); assert(0 == fclose(fp)); assert(~puts("Ok")); } void test2() { const char *buf = "hello world"; FILE *fp = fopen(NULL, "rb"); assert(fwrite(buf, strlen(buf), 1, fp)); puts(*fdata(fp)); assert(0 == fclose(fp)); assert(~puts("Ok")); } void test3() { FILE *fp = fopen(NULL, "rb"); assert(fprintf(fp, "hello %s! %d\n", "world", 123)); puts(*fdata(fp)); assert(0 == fclose(fp)); assert(~puts("Ok")); } int main() { test1(); test2(); test3(); }