diff options
Diffstat (limited to 'src/gfile/gfile.c')
-rw-r--r-- | src/gfile/gfile.c | 385 |
1 files changed, 137 insertions, 248 deletions
diff --git a/src/gfile/gfile.c b/src/gfile/gfile.c index caf7f22f..595bba1f 100644 --- a/src/gfile/gfile.c +++ b/src/gfile/gfile.c @@ -11,183 +11,65 @@ * */ -#define GFILE_IMPLEMENTATION - #include "gfx.h" #if GFX_USE_GFILE -struct GFILE { - const struct GFILEVMT * vmt; - uint16_t flags; - #define GFILEFLG_OPEN 0x0001 // File is open - #define GFILEFLG_READ 0x0002 // Read the file - #define GFILEFLG_WRITE 0x0004 // Write the file - #define GFILEFLG_APPEND 0x0008 // Append on each write - #define GFILEFLG_BINARY 0x0010 // Treat as a binary file - #define GFILEFLG_DELONCLOSE 0x0020 // Delete on close - #define GFILEFLG_CANSEEK 0x0040 // Seek operations are valid - #define GFILEFLG_FAILONBLOCK 0x0080 // Fail on a blocking call - #define GFILEFLG_MUSTEXIST 0x0100 // On open file must exist - #define GFILEFLG_MUSTNOTEXIST 0x0200 // On open file must not exist - #define GFILEFLG_TRUNC 0x0400 // On open truncate the file - void * obj; - long int pos; -}; - -struct gfileList { - const struct GFILEVMT * vmt; - bool_t dirs; -}; - -typedef struct GFILEVMT { - const struct GFILEVMT * next; - uint8_t flags; - #define GFSFLG_WRITEABLE 0x0001 - #define GFSFLG_CASESENSITIVE 0x0002 - #define GFSFLG_SEEKABLE 0x0004 - #define GFSFLG_FAST 0x0010 - #define GFSFLG_SMALL 0x0020 - #define GFSFLG_TEXTMODES 0x0040 - char prefix; - bool_t (*del) (const char *fname); - bool_t (*exists) (const char *fname); - long int (*filesize) (const char *fname); - bool_t (*ren) (const char *oldname, const char *newname); - bool_t (*open) (GFILE *f, const char *fname); - void (*close) (GFILE *f); - int (*read) (GFILE *f, void *buf, int size); - int (*write) (GFILE *f, const void *buf, int size); - bool_t (*setpos) (GFILE *f, long int pos); - long int (*getsize) (GFILE *f); - bool_t (*eof) (GFILE *f); - bool_t (*mount) (const char *drive); - bool_t (*unmount) (const char *drive); - bool_t (*sync) (GFILE *f); - #if GFILE_NEED_FILELISTS - gfileList * (*flopen) (const char *path, bool_t dirs); - const char *(*flread) (gfileList *pfl); - void (*flclose) (gfileList *pfl); - #endif -} GFILEVMT; - -// The chain of FileSystems -#define GFILE_CHAINHEAD 0 - -// The table of GFILE's -static GFILE gfileArr[GFILE_MAX_GFILES]; -GFILE *gfileStdIn; -GFILE *gfileStdOut; -GFILE *gfileStdErr; - -// Forward definition used by some special open calls -static GFILE *findemptyfile(const char *mode); +#include "gfile_fs.h" /** - * The order of the file-systems below determines the order - * that they are searched to find a file. - * The last defined is the first searched. + * Define the VMT's for the file-systems we want to search for files. + * Virtual file-systems that have special open() calls do not need to + * be in this list. */ - -/******************************************************** - * The ChibiOS BaseFileStream VMT - ********************************************************/ -#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS - #include "src/gfile/inc_chibiosfs.c" -#endif - -/******************************************************** - * The Memory Pointer VMT - ********************************************************/ -#if GFILE_NEED_MEMFS - #include "src/gfile/inc_memfs.c" -#endif - -/******************************************************** - * The RAM file-system VMT - ********************************************************/ -#if GFILE_NEED_RAMFS - #include "src/gfile/inc_ramfs.c" -#endif - -/******************************************************** - * The FAT file-system VMT - ********************************************************/ -#if GFILE_NEED_FATFS - #include "src/gfile/inc_fatfs.c" -#endif - -/******************************************************** - * The native file-system - ********************************************************/ -#if GFILE_NEED_NATIVEFS - #include "src/gfile/inc_nativefs.c" -#endif - -/******************************************************** - * The ROM file-system VMT - ********************************************************/ #if GFILE_NEED_ROMFS - #include "src/gfile/inc_romfs.c" -#endif - -/******************************************************** - * The virtual string file VMT - ********************************************************/ -#if GFILE_NEED_STRINGS - #include "src/gfile/inc_strings.c" + extern const GFILEVMT FsROMVMT; #endif - -/******************************************************** - * Printg Routines - ********************************************************/ -#if GFILE_NEED_PRINTG - #include "src/gfile/inc_printg.c" +#if GFILE_NEED_NATIVEFS + extern const GFILEVMT FsNativeVMT; #endif - -/******************************************************** - * Scang Routines - ********************************************************/ -#if GFILE_NEED_SCANG - #include "src/gfile/inc_scang.c" +#if GFILE_NEED_FATFS + extern const GFILEVMT FsFatFSVMT; #endif - -/******************************************************** - * Stdio Emulation Routines - ********************************************************/ -#if GFILE_NEED_STDIO - #include "src/gfile/inc_stdio.c" +#if GFILE_NEED_RAMFS + extern const GFILEVMT FsRAMVMT; #endif -/******************************************************** - * IO routines - ********************************************************/ /** - * The chain of file systems. + * The order of the file-systems below determines the order + * that they are searched to find a file. */ -static const GFILEVMT const * FsChain = GFILE_CHAINHEAD; +static const GFILEVMT const * FsArray[] = { + #if GFILE_NEED_ROMFS + &FsROMVMT, + #endif + #if GFILE_NEED_NATIVEFS + &FsNativeVMT, + #endif + #if GFILE_NEED_FATFS + &FsFatFSVMT, + #endif + #if GFILE_NEED_RAMFS + &FsRAMVMT, + #endif +}; + +/* + * The table of GFILE's + */ +static GFILE gfileArr[GFILE_MAX_GFILES]; +GFILE *gfileStdIn; +GFILE *gfileStdOut; +GFILE *gfileStdErr; /** * The init routine */ void _gfileInit(void) { #if GFILE_NEED_NATIVEFS - NativeStdIn.flags = GFILEFLG_OPEN|GFILEFLG_READ; - NativeStdIn.vmt = &FsNativeVMT; - NativeStdIn.obj = (void *)stdin; - NativeStdIn.pos = 0; - gfileStdIn = &NativeStdIn; - NativeStdOut.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND; - NativeStdOut.vmt = &FsNativeVMT; - NativeStdOut.obj = (void *)stdout; - NativeStdOut.pos = 0; - gfileStdOut = &NativeStdOut; - NativeStdErr.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND; - NativeStdErr.vmt = &FsNativeVMT; - NativeStdErr.obj = (void *)stderr; - NativeStdErr.pos = 0; - gfileStdErr = &NativeStdErr; + extern void _gfileNativeAssignStdio(void); + _gfileNativeAssignStdio(); #endif } @@ -196,69 +78,122 @@ void _gfileDeinit(void) /* ToDo */ } +/** + * Internal routine to find an empty GFILE slot and interpret flags. + */ +GFILE *_gfileFindSlot(const char *mode) { + GFILE * f; + + // First find an available GFILE slot. + for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) { + if (!(f->flags & GFILEFLG_OPEN)) { + // Get the flags + switch(mode[0]) { + case 'r': + f->flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST; + while (*++mode) { + switch(mode[0]) { + case '+': f->flags |= GFILEFLG_WRITE; break; + case 'b': f->flags |= GFILEFLG_BINARY; break; + } + } + break; + case 'w': + f->flags = GFILEFLG_WRITE|GFILEFLG_TRUNC; + while (*++mode) { + switch(mode[0]) { + case '+': f->flags |= GFILEFLG_READ; break; + case 'b': f->flags |= GFILEFLG_BINARY; break; + case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break; + } + } + break; + case 'a': + f->flags = GFILEFLG_WRITE|GFILEFLG_APPEND; + while (*++mode) { + switch(mode[0]) { + case '+': f->flags |= GFILEFLG_READ; break; + case 'b': f->flags |= GFILEFLG_BINARY; break; + case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break; + } + } + break; + default: + return 0; + } + return f; + } + } + return 0; +} + +/******************************************************** + * IO routines + ********************************************************/ + bool_t gfileExists(const char *fname) { - const GFILEVMT *p; + const GFILEVMT * const *p; #if GFILE_ALLOW_DEVICESPECIFIC if (fname[0] && fname[1] == '|') { - for(p = FsChain; p; p = p->next) { - if (p->prefix == fname[0]) - return p->exists && p->exists(fname+2); + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fname[0]) + return p[0]->exists && p[0]->exists(fname+2); } return FALSE; } #endif - for(p = FsChain; p; p = p->next) { - if (p->exists && p->exists(fname)) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->exists && p[0]->exists(fname)) return TRUE; } return FALSE; } bool_t gfileDelete(const char *fname) { - const GFILEVMT *p; + const GFILEVMT **p; #if GFILE_ALLOW_DEVICESPECIFIC if (fname[0] && fname[1] == '|') { - for(p = FsChain; p; p = p->next) { - if (p->prefix == fname[0]) - return p->del && p->del(fname+2); + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fname[0]) + return p[0]->del && p[0]->del(fname+2); } return FALSE; } #endif - for(p = FsChain; p; p = p->next) { - if (p->del && p->del(fname)) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->del && p[0]->del(fname)) return TRUE; } return FALSE; } long int gfileGetFilesize(const char *fname) { - const GFILEVMT *p; + const GFILEVMT * const *p; long int res; #if GFILE_ALLOW_DEVICESPECIFIC if (fname[0] && fname[1] == '|') { - for(p = FsChain; p; p = p->next) { - if (p->prefix == fname[0]) - return p->filesize ? p->filesize(fname+2) : -1; + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fname[0]) + return p[0]->filesize ? p[0]->filesize(fname+2) : -1; } return -1; } #endif - for(p = FsChain; p; p = p->next) { - if (p->filesize && (res = p->filesize(fname)) != -1) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->filesize && (res = p[0]->filesize(fname)) != -1) return res; } return -1; } bool_t gfileRename(const char *oldname, const char *newname) { - const GFILEVMT *p; + const GFILEVMT * const *p; #if GFILE_ALLOW_DEVICESPECIFIC if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) { @@ -277,67 +212,21 @@ bool_t gfileRename(const char *oldname, const char *newname) { ch = newname[0]; newname += 2; } - for(p = FsChain; p; p = p->next) { - if (p->prefix == ch) - return p->ren && p->ren(oldname, newname); + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == ch) + return p[0]->ren && p[0]->ren(oldname, newname); } return FALSE; } #endif - for(p = FsChain; p; p = p->next) { - if (p->ren && p->ren(oldname,newname)) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->ren && p[0]->ren(oldname,newname)) return TRUE; } return FALSE; } -static GFILE *findemptyfile(const char *mode) { - GFILE * f; - - // First find an available GFILE slot. - for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) { - if (!(f->flags & GFILEFLG_OPEN)) { - // Get the flags - switch(mode[0]) { - case 'r': - f->flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST; - while (*++mode) { - switch(mode[0]) { - case '+': f->flags |= GFILEFLG_WRITE; break; - case 'b': f->flags |= GFILEFLG_BINARY; break; - } - } - break; - case 'w': - f->flags = GFILEFLG_WRITE|GFILEFLG_TRUNC; - while (*++mode) { - switch(mode[0]) { - case '+': f->flags |= GFILEFLG_READ; break; - case 'b': f->flags |= GFILEFLG_BINARY; break; - case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break; - } - } - break; - case 'a': - f->flags = GFILEFLG_WRITE|GFILEFLG_APPEND; - while (*++mode) { - switch(mode[0]) { - case '+': f->flags |= GFILEFLG_READ; break; - case 'b': f->flags |= GFILEFLG_BINARY; break; - case 'x': f->flags |= GFILEFLG_MUSTNOTEXIST; break; - } - } - break; - default: - return 0; - } - return f; - } - } - return 0; -} - static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) { // If we want write but the fs doesn't allow it then return if ((f->flags & GFILEFLG_WRITE) && !(p->flags & GFSFLG_WRITEABLE)) @@ -358,17 +247,17 @@ static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) { GFILE *gfileOpen(const char *fname, const char *mode) { GFILE * f; - const GFILEVMT *p; + const GFILEVMT * const *p; // Get an empty file and set the flags - if (!(f = findemptyfile(mode))) + if (!(f = _gfileFindSlot(mode))) return 0; #if GFILE_ALLOW_DEVICESPECIFIC if (fname[0] && fname[1] == '|') { - for(p = FsChain; p; p = p->next) { - if (p->prefix == fname[0]) - return testopen(p, f, fname+2) ? f : 0; + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fname[0]) + return testopen(p[0], f, fname+2) ? f : 0; } // File not found @@ -376,8 +265,8 @@ GFILE *gfileOpen(const char *fname, const char *mode) { } #endif - for(p = FsChain; p; p = p->next) { - if (testopen(p, f, fname)) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (testopen(p[0], f, fname)) return f; } @@ -451,28 +340,28 @@ bool_t gfileEOF(GFILE *f) { } bool_t gfileMount(char fs, const char* drive) { - const GFILEVMT *p; + const GFILEVMT * const *p; // Find the correct VMT - for(p = FsChain; p; p = p->next) { - if (p->prefix == fs) { - if (!p->mount) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fs) { + if (!p[0]->mount) return FALSE; - return p->mount(drive); + return p[0]->mount(drive); } } return FALSE; } bool_t gfileUnmount(char fs, const char* drive) { - const GFILEVMT *p; + const GFILEVMT * const *p; // Find the correct VMT - for(p = FsChain; p; p = p->next) { - if (p->prefix == fs) { - if (!p->mount) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fs) { + if (!p[0]->mount) return FALSE; - return p->unmount(drive); + return p[0]->unmount(drive); } } return FALSE; @@ -486,17 +375,17 @@ bool_t gfileSync(GFILE *f) { #if GFILE_NEED_FILELISTS gfileList *gfileOpenFileList(char fs, const char *path, bool_t dirs) { - const GFILEVMT *p; + const GFILEVMT * const *p; gfileList * pfl; // Find the correct VMT - for(p = FsChain; p; p = p->next) { - if (p->prefix == fs) { - if (!p->flopen) + for(p = FsArray; p < &FsArray[sizeof(FsArray)/sizeof(FsArray[0])]; p++) { + if (p[0]->prefix == fs) { + if (!p[0]->flopen) return 0; - pfl = p->flopen(path, dirs); + pfl = p[0]->flopen(path, dirs); if (pfl) { - pfl->vmt = p; + pfl->vmt = p[0]; pfl->dirs = dirs; } return pfl; |