More GFile code
This commit is contained in:
parent
c5ab2adbf0
commit
5bba108949
5 changed files with 530 additions and 123 deletions
|
@ -45,7 +45,6 @@ typedef struct GFILE {
|
||||||
#define GFILEFLG_MUSTEXIST 0x0100 // On open file must exist
|
#define GFILEFLG_MUSTEXIST 0x0100 // On open file must exist
|
||||||
#define GFILEFLG_MUSTNOTEXIST 0x0200 // On open file must not exist
|
#define GFILEFLG_MUSTNOTEXIST 0x0200 // On open file must not exist
|
||||||
#define GFILEFLG_TRUNC 0x0400 // On open truncate the file
|
#define GFILEFLG_TRUNC 0x0400 // On open truncate the file
|
||||||
short err;
|
|
||||||
void * obj;
|
void * obj;
|
||||||
long int pos;
|
long int pos;
|
||||||
} GFILE;
|
} GFILE;
|
||||||
|
@ -58,6 +57,7 @@ typedef struct GFILEVMT {
|
||||||
#define GFSFLG_SEEKABLE 0x0004
|
#define GFSFLG_SEEKABLE 0x0004
|
||||||
#define GFSFLG_FAST 0x0010
|
#define GFSFLG_FAST 0x0010
|
||||||
#define GFSFLG_SMALL 0x0020
|
#define GFSFLG_SMALL 0x0020
|
||||||
|
#define GFSFLG_TEXTMODES 0x0040
|
||||||
char prefix;
|
char prefix;
|
||||||
bool_t del(const char *fname);
|
bool_t del(const char *fname);
|
||||||
bool_t exists(const char *fname);
|
bool_t exists(const char *fname);
|
||||||
|
@ -66,7 +66,7 @@ typedef struct GFILEVMT {
|
||||||
bool_t open(GFILE *f, const char *fname);
|
bool_t open(GFILE *f, const char *fname);
|
||||||
void close(GFILE *f);
|
void close(GFILE *f);
|
||||||
int read(GFILE *f, char *buf, int size);
|
int read(GFILE *f, char *buf, int size);
|
||||||
int write(GFILE *f, char *buf, int size);
|
int write(GFILE *f, const char *buf, int size);
|
||||||
bool_t setpos(GFILE *f, long int pos);
|
bool_t setpos(GFILE *f, long int pos);
|
||||||
long int getsize(GFILE *f);
|
long int getsize(GFILE *f);
|
||||||
bool_t eof(GFILE *f);
|
bool_t eof(GFILE *f);
|
||||||
|
@ -112,37 +112,46 @@ extern GFILE *gfileStdOut;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool_t gfileExists(const char *fname);
|
bool_t gfileExists(const char *fname);
|
||||||
bool_t gfileDelete(const char *fname);
|
bool_t gfileDelete(const char *fname);
|
||||||
long int gfileGetFilesize(const char *fname);
|
long int gfileGetFilesize(const char *fname);
|
||||||
bool_t gfileRename(const char *oldname, const char *newname);
|
bool_t gfileRename(const char *oldname, const char *newname);
|
||||||
GFILE *gfileOpen(const char *fname, const char *mode);
|
GFILE * gfileOpen(const char *fname, const char *mode);
|
||||||
void gfileClose(GFILE *f);
|
void gfileClose(GFILE *f);
|
||||||
size_t gfileRead(GFILE *f, char *buf, size_t len);
|
size_t gfileRead(GFILE *f, char *buf, size_t len);
|
||||||
size_t gfileWrite(GFILE *f, const char *buf, size_t len);
|
size_t gfileWrite(GFILE *f, const char *buf, size_t len);
|
||||||
long int gfileGetPos(GFILE *f);
|
long int gfileGetPos(GFILE *f);
|
||||||
bool_t gfileSetPos(GFILE *f, long int pos);
|
bool_t gfileSetPos(GFILE *f, long int pos);
|
||||||
long int gfileGetSize(GFILE *f);
|
long int gfileGetSize(GFILE *f);
|
||||||
|
bool_t gfileEOF(GFILE *f);
|
||||||
|
|
||||||
int vfnprintg(GFILE *f, size_t maxlen, const char *fmt, va_list arg);
|
#if GFILE_NEED_PRINTG
|
||||||
int fnprintg(GFILE *f, size_t maxlen, const char *fmt, ...);
|
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg);
|
||||||
#define vfprintg(f,m,a) vfnprintg(f,0,m,a)
|
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...);
|
||||||
#define fprintg(f,m,...) fnprintg(f,0,m,...)
|
#define vfprintg(f,m,a) vfnprintg(f,0,m,a)
|
||||||
#define vprintg(m,a) vfnprintg(gfileStdOut,0,m,a)
|
#define fprintg(f,m,...) fnprintg(f,0,m,...)
|
||||||
#define printg(m,...) fnprintg(gfileStdOut,0,m,...)
|
#define vprintg(m,a) vfnprintg(gfileStdOut,0,m,a)
|
||||||
|
#define printg(m,...) fnprintg(gfileStdOut,0,m,...)
|
||||||
|
|
||||||
|
#if GFILE_NEED_STRINGS
|
||||||
|
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg);
|
||||||
|
int snprintg(char *buf, int maxlen, const char *fmt, ...);
|
||||||
|
#define vsprintg(s,m,a) vsnprintg(s,0,m,a)
|
||||||
|
#define sprintg(s,m,...) snprintg(s,0,m,...)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
int vsnprintg(char *buf, size_t maxlen, const char *fmt, va_list arg);
|
|
||||||
int snprintg(char *buf, size_t maxlen, const char *fmt, ...);
|
|
||||||
#define vsprintg(s,m,a) vsnprintg(s,0,m,a)
|
|
||||||
#define sprintg(s,m,...) snprintg(s,0,m,...)
|
|
||||||
|
|
||||||
#if GFILE_NEED_STDIO && !defined(GFILE_IMPLEMENTATION)
|
#if GFILE_NEED_STDIO && !defined(GFILE_IMPLEMENTATION)
|
||||||
#define FILE GFILE
|
#define FILE GFILE
|
||||||
#define fopen(n,m) gfileOpen(n,m)
|
#define fopen(n,m) gfileOpen(n,m)
|
||||||
#define fclose(f) gfileClose(f)
|
#define fclose(f) gfileClose(f)
|
||||||
size_t fread(void * ptr, size_t size, size_t count, FILE *f);
|
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f);
|
||||||
size_t fwrite(const void * ptr, size_t size, size_t count, FILE *f);
|
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f);
|
||||||
int fseek(FILE *f, size_t offset, int origin);
|
#define fread(p,sz,cnt,f) gstdioRead(p,sz,cnt,f)
|
||||||
|
#define fwrite(p,sz,cnt,f) gstdioWrite(p,sz,cnt,f)
|
||||||
|
int gstdioSeek(FILE *f, size_t offset, int origin);
|
||||||
|
#define fseek(f,ofs,org) gstdioSeek(f,ofs,org)
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
#define SEEK_END 2
|
#define SEEK_END 2
|
||||||
|
@ -150,13 +159,14 @@ extern "C" {
|
||||||
#define rename(o,n) (!gfileRename(o,n))
|
#define rename(o,n) (!gfileRename(o,n))
|
||||||
#define fflush(f) (0)
|
#define fflush(f) (0)
|
||||||
#define ftell(f) gfileGetPos(f)
|
#define ftell(f) gfileGetPos(f)
|
||||||
typedef long int fpos_t;
|
#define fpos_t long int
|
||||||
int fgetpos(FILE *f, fpos_t *pos);
|
int gstdioGetpos(FILE *f, long int *pos);
|
||||||
|
#define fgetpos(f,pos) gstdioGetpos(f,pos)
|
||||||
#define fsetpos(f, pos) (!gfileSetPos(f, *pos))
|
#define fsetpos(f, pos) (!gfileSetPos(f, *pos))
|
||||||
#define rewind(f) gfileSetPos(f, 0);
|
#define rewind(f) gfileSetPos(f, 0);
|
||||||
#define clearerr(f) do {f->err = 0; } while(0)
|
#define clearerr(f) (0)
|
||||||
#define feof(f) (f->flags & GFILEFLG_EOF)
|
#define feof(f) gfileEOF(f)
|
||||||
#define ferror(f) (f->err)
|
//#define ferror(f) (0)
|
||||||
|
|
||||||
#define vfprintf(f,m,a) vfnprintg(f,0,m,a)
|
#define vfprintf(f,m,a) vfnprintg(f,0,m,a)
|
||||||
#define fprintf(f,m,...) fnprintg(f,0,m,...)
|
#define fprintf(f,m,...) fnprintg(f,0,m,...)
|
||||||
|
|
|
@ -21,12 +21,28 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @brief Include printg, fprintg, sprintg etc functions
|
* @brief Include printg, fprintg etc functions
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
*/
|
*/
|
||||||
#ifndef GFILE_NEED_PRINTG
|
#ifndef GFILE_NEED_PRINTG
|
||||||
#define GFILE_NEED_PRINTG FALSE
|
#define GFILE_NEED_PRINTG FALSE
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Include scang, fscang etc functions
|
||||||
|
* @details Defaults to FALSE
|
||||||
|
*/
|
||||||
|
#ifndef GFILE_NEED_SCANG
|
||||||
|
#define GFILE_NEED_SCANG FALSE
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Include the string sprintg/sscang functions
|
||||||
|
* @details Defaults to FALSE
|
||||||
|
* @pre To get sprintg functions you also need to define @p GFILE_NEED_PRINTG
|
||||||
|
* @pre To get sscang functions you also need to define @p GFILE_NEED_SCANG
|
||||||
|
*/
|
||||||
|
#ifndef GFILE_NEED_STRINGS
|
||||||
|
#define GFILE_NEED_STRINGS FALSE
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Include scang, fscang, sscang etc functions
|
* @brief Include scang, fscang, sscang etc functions
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
|
@ -35,7 +51,7 @@
|
||||||
#define GFILE_NEED_SCANG FALSE
|
#define GFILE_NEED_SCANG FALSE
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Map all the stdio functions to their GFILE equivalent
|
* @brief Map many stdio functions to their GFILE equivalent
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note This replaces the functions in stdio.h with equivalents
|
* @note This replaces the functions in stdio.h with equivalents
|
||||||
* - Do not include stdio.h as it has different conflicting definitions.
|
* - Do not include stdio.h as it has different conflicting definitions.
|
||||||
|
@ -46,7 +62,8 @@
|
||||||
/**
|
/**
|
||||||
* @brief Include the ROM file system
|
* @brief Include the ROM file system
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note To ensure that you are opening a file on the ROM file system, prefix
|
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||||
|
* opening a file on the ROM file system by prefixing
|
||||||
* its name with "S|" (the letter 'S', followed by a vertical bar).
|
* its name with "S|" (the letter 'S', followed by a vertical bar).
|
||||||
* @note This requires a file called romfs_files.h to be included in the
|
* @note This requires a file called romfs_files.h to be included in the
|
||||||
* users project. This file includes all the files converted to .h files
|
* users project. This file includes all the files converted to .h files
|
||||||
|
@ -58,7 +75,8 @@
|
||||||
/**
|
/**
|
||||||
* @brief Include the RAM file system
|
* @brief Include the RAM file system
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note To ensure that you are opening a file on the RAM file system, prefix
|
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||||
|
* opening a file on the RAM file system by prefixing
|
||||||
* its name with "R|" (the letter 'R', followed by a vertical bar).
|
* its name with "R|" (the letter 'R', followed by a vertical bar).
|
||||||
* @note You must also define GFILE_RAMFS_SIZE with the size of the file system
|
* @note You must also define GFILE_RAMFS_SIZE with the size of the file system
|
||||||
* to be allocated in RAM.
|
* to be allocated in RAM.
|
||||||
|
@ -69,7 +87,8 @@
|
||||||
/**
|
/**
|
||||||
* @brief Include the FAT file system driver
|
* @brief Include the FAT file system driver
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note To ensure that you are opening a file on the FAT file system, prefix
|
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||||
|
* opening a file on the FAT file system by prefixing
|
||||||
* its name with "F|" (the letter 'F', followed by a vertical bar).
|
* its name with "F|" (the letter 'F', followed by a vertical bar).
|
||||||
* @note You must separately include the FATFS library and code.
|
* @note You must separately include the FATFS library and code.
|
||||||
*/
|
*/
|
||||||
|
@ -79,7 +98,8 @@
|
||||||
/**
|
/**
|
||||||
* @brief Include the operating system's native file system
|
* @brief Include the operating system's native file system
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
* @note To ensure that you are opening a file on the native file system, prefix
|
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||||
|
* opening a file on the native file system by prefixing
|
||||||
* its name with "N|" (the letter 'N', followed by a vertical bar).
|
* its name with "N|" (the letter 'N', followed by a vertical bar).
|
||||||
* @note If defined then the gfileStdOut and gfileStdErr handles
|
* @note If defined then the gfileStdOut and gfileStdErr handles
|
||||||
* use the operating system equivalent stdio and stderr.
|
* use the operating system equivalent stdio and stderr.
|
||||||
|
@ -94,6 +114,21 @@
|
||||||
* @name GFILE Optional Parameters
|
* @name GFILE Optional Parameters
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @brief Add floating point support to printg/scang etc.
|
||||||
|
*/
|
||||||
|
#ifndef GFILE_ALLOW_FLOATS
|
||||||
|
#define GFILE_ALLOW_FLOATS
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Can the device be specified as part of the file name.
|
||||||
|
* @note If this is on then a device letter and a vertical bar can be
|
||||||
|
* prefixed on a file name to specify that it must be on a
|
||||||
|
* specific device.
|
||||||
|
*/
|
||||||
|
#ifndef GFILE_ALLOW_DEVICESPECIFIC
|
||||||
|
#define GFILE_ALLOW_DEVICESPECIFIC FALSE
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief The maximum number of open files
|
* @brief The maximum number of open files
|
||||||
* @note This count excludes gfileStdIn, gfileStdOut and gfileStdErr
|
* @note This count excludes gfileStdIn, gfileStdOut and gfileStdErr
|
||||||
|
|
|
@ -91,87 +91,98 @@ void _gfileInit(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gfileExists(const char *fname) {
|
bool_t gfileExists(const char *fname) {
|
||||||
const GFILEVMT *p;
|
const GFILEVMT *p;
|
||||||
|
|
||||||
if (fname[0] && fname[1] == '|') {
|
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||||
for(p = FsChain; p; p = p->next) {
|
if (fname[0] && fname[1] == '|') {
|
||||||
if (p->prefix == fname[0])
|
for(p = FsChain; p; p = p->next) {
|
||||||
return p->exists && p->exists(fname+2);
|
if (p->prefix == fname[0])
|
||||||
}
|
return p->exists && p->exists(fname+2);
|
||||||
} else {
|
}
|
||||||
for(p = FsChain; p; p = p->next) {
|
return FALSE;
|
||||||
if (p->exists && p->exists(fname))
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(p = FsChain; p; p = p->next) {
|
||||||
|
if (p->exists && p->exists(fname))
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gfileDelete(const char *fname) {
|
bool_t gfileDelete(const char *fname) {
|
||||||
const GFILEVMT *p;
|
const GFILEVMT *p;
|
||||||
|
|
||||||
if (fname[0] && fname[1] == '|') {
|
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||||
for(p = FsChain; p; p = p->next) {
|
if (fname[0] && fname[1] == '|') {
|
||||||
if (p->prefix == fname[0])
|
for(p = FsChain; p; p = p->next) {
|
||||||
return p->del && p->del(fname+2);
|
if (p->prefix == fname[0])
|
||||||
}
|
return p->del && p->del(fname+2);
|
||||||
} else {
|
}
|
||||||
for(p = FsChain; p; p = p->next) {
|
return FALSE;
|
||||||
if (p->del && p->del(fname))
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(p = FsChain; p; p = p->next) {
|
||||||
|
if (p->del && p->del(fname))
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int gfileGetFilesize(const char *fname) {
|
long int gfileGetFilesize(const char *fname) {
|
||||||
const GFILEVMT *p;
|
const GFILEVMT *p;
|
||||||
|
long int res;
|
||||||
|
|
||||||
if (fname[0] && fname[1] == '|') {
|
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||||
for(p = FsChain; p; p = p->next) {
|
if (fname[0] && fname[1] == '|') {
|
||||||
if (p->prefix == fname[0])
|
for(p = FsChain; p; p = p->next) {
|
||||||
return p->filesize ? p->filesize(fname+2) : -1;
|
if (p->prefix == fname[0])
|
||||||
|
return p->filesize ? p->filesize(fname+2) : -1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
#endif
|
||||||
long int res;
|
|
||||||
|
|
||||||
for(p = FsChain; p; p = p->next) {
|
for(p = FsChain; p; p = p->next) {
|
||||||
if (p->filesize && (res = p->filesize(fname)) != -1)
|
if (p->filesize && (res = p->filesize(fname)) != -1)
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gfileRename(const char *oldname, const char *newname) {
|
bool_t gfileRename(const char *oldname, const char *newname) {
|
||||||
const GFILEVMT *p;
|
const GFILEVMT *p;
|
||||||
|
|
||||||
if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) {
|
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||||
char ch;
|
if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) {
|
||||||
|
char ch;
|
||||||
|
|
||||||
if (oldname[0] && oldname[1] == '|') {
|
if (oldname[0] && oldname[1] == '|') {
|
||||||
ch = oldname[0];
|
ch = oldname[0];
|
||||||
oldname += 2;
|
oldname += 2;
|
||||||
if (newname[0] && newname[1] == '|') {
|
if (newname[0] && newname[1] == '|') {
|
||||||
if (newname[0] != ch)
|
if (newname[0] != ch)
|
||||||
// Both oldname and newname are fs specific but different ones.
|
// Both oldname and newname are fs specific but different ones.
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
newname += 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ch = newname[0];
|
||||||
newname += 2;
|
newname += 2;
|
||||||
}
|
}
|
||||||
} else {
|
for(p = FsChain; p; p = p->next) {
|
||||||
ch = newname[0];
|
if (p->prefix == ch)
|
||||||
newname += 2;
|
return p->ren && p->ren(oldname, newname);
|
||||||
}
|
}
|
||||||
for(p = FsChain; p; p = p->next) {
|
return FALSE;
|
||||||
if (p->prefix == ch)
|
|
||||||
return p->ren && p->ren(oldname, newname);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(p = FsChain; p; p = p->next) {
|
|
||||||
if (p->ren && p->ren(oldname,newname))
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(p = FsChain; p; p = p->next) {
|
||||||
|
if (p->ren && p->ren(oldname,newname))
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -233,32 +244,47 @@ static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GFILE *gfileOpen(const char *fname, const char *mode) {
|
GFILE *gfileOpen(const char *fname, const char *mode) {
|
||||||
GFILE *f;
|
uint16_t flags;
|
||||||
|
GFILE * f;
|
||||||
const GFILEVMT *p;
|
const GFILEVMT *p;
|
||||||
|
|
||||||
|
// Get the requested mode
|
||||||
|
if (!(flags = mode2flags(mode)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||||
|
if (fname[0] && fname[1] == '|') {
|
||||||
|
// First find an available GFILE slot.
|
||||||
|
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||||
|
// Try to open the file
|
||||||
|
f->flags = flags;
|
||||||
|
for(p = FsChain; p; p = p->next) {
|
||||||
|
if (p->prefix == fname[0])
|
||||||
|
return testopen(p, f, fname+2);
|
||||||
|
}
|
||||||
|
// File not found
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No available slot
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// First find an available GFILE slot.
|
// First find an available GFILE slot.
|
||||||
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||||
if (!(f->flags & GFILEFLG_OPEN)) {
|
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||||
|
|
||||||
// Get the requested mode
|
|
||||||
if (!(f->flags = mode2flags(mode)))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
// Try to open the file
|
// Try to open the file
|
||||||
if (fname[0] && fname[1] == '|') {
|
f->flags = flags;
|
||||||
for(p = FsChain; p; p = p->next) {
|
for(p = FsChain; p; p = p->next) {
|
||||||
if (p->prefix == fname[0])
|
if (testopen(p, f, fname))
|
||||||
return testopen(p, f, fname+2);
|
return TRUE;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(p = FsChain; p; p = p->next) {
|
|
||||||
if (testopen(p, f, fname))
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File not found
|
// File not found
|
||||||
return FALSE;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,48 +293,384 @@ GFILE *gfileOpen(const char *fname, const char *mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfileClose(GFILE *f) {
|
void gfileClose(GFILE *f) {
|
||||||
// Make sure it is one of the system GFILE's
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
if (f < gfileArr || f >= &gfileArr[GFILE_MAX_GFILES])
|
|
||||||
return;
|
return;
|
||||||
|
if (f->vmt->close)
|
||||||
|
f->vmt->close(f);
|
||||||
|
f->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gfileRead(GFILE *f, char *buf, size_t len) {
|
size_t gfileRead(GFILE *f, char *buf, size_t len) {
|
||||||
|
size_t res;
|
||||||
|
|
||||||
|
if ((f->flags & (GFILEFLG_OPEN|GFILEFLG_READ)) != (GFILEFLG_OPEN|GFILEFLG_READ))
|
||||||
|
return 0;
|
||||||
|
if (!f->vmt->read)
|
||||||
|
return 0;
|
||||||
|
if ((res = f->vmt->read(f, buf, len)) <= 0)
|
||||||
|
return 0;
|
||||||
|
f->pos += res;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gfileWrite(GFILE *f, const char *buf, size_t len) {
|
size_t gfileWrite(GFILE *f, const char *buf, size_t len) {
|
||||||
|
size_t res;
|
||||||
|
|
||||||
|
if ((f->flags & (GFILEFLG_OPEN|GFILEFLG_WRITE)) != (GFILEFLG_OPEN|GFILEFLG_WRITE))
|
||||||
|
return 0;
|
||||||
|
if (!f->vmt->write)
|
||||||
|
return 0;
|
||||||
|
if ((res = f->vmt->write(f, buf, len)) <= 0)
|
||||||
|
return 0;
|
||||||
|
f->pos += res;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int gfileGetPos(GFILE *f) {
|
long int gfileGetPos(GFILE *f) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
|
return 0;
|
||||||
|
return f->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gfileSetPos(GFILE *f, long int pos) {
|
bool_t gfileSetPos(GFILE *f, long int pos) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
|
return FALSE;
|
||||||
|
if (!f->vmt->setpos || !f->vmt->setpos(f, pos))
|
||||||
|
return FALSE;
|
||||||
|
f->pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int gfileGetSize(GFILE *f) {
|
long int gfileGetSize(GFILE *f) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
|
return 0;
|
||||||
|
if (!f->vmt->getsize)
|
||||||
|
return 0;
|
||||||
|
return f->vmt->getsize(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t gfileEOF(GFILE *f) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
|
return TRUE;
|
||||||
|
if (!f->vmt->eof)
|
||||||
|
return TRUE;
|
||||||
|
return f->vmt->eof(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
* String VMT routines
|
||||||
|
********************************************************/
|
||||||
|
#if GFILE_NEED_STRINGS && (GFILE_NEED_PRINTG || GFILE_NEED_SCANG)
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Special String VMT
|
||||||
|
static int StringRead(GFILE *f, char *buf, int size) {
|
||||||
|
memcpy(buf, (char *)f->obj+f->pos, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
static int StringWrite(GFILE *f, const char *buf, int size) {
|
||||||
|
memcpy((char *)f->obj+f->pos, buf, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
static const GFILEVMT StringVMT = {
|
||||||
|
0, // next
|
||||||
|
0, // flags
|
||||||
|
'_', // prefix
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, StringRead, StringWrite,
|
||||||
|
0, 0, 0,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* printg routines
|
* printg routines
|
||||||
********************************************************/
|
********************************************************/
|
||||||
#if GFILE_NEED_PRINTG
|
#if GFILE_NEED_PRINTG
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define MAX_FILLER 11
|
||||||
|
#define FLOAT_PRECISION 100000
|
||||||
|
|
||||||
|
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...) {
|
||||||
|
int res;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
res = vfnprintg(f, maxlen, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) {
|
||||||
|
int i;
|
||||||
|
char * q;
|
||||||
|
|
||||||
|
if (!divisor) divisor = num;
|
||||||
|
|
||||||
|
q = p + MAX_FILLER;
|
||||||
|
do {
|
||||||
|
i = (int)(num % radix);
|
||||||
|
i += '0';
|
||||||
|
if (i > '9')
|
||||||
|
i += 'A' - '0' - 10;
|
||||||
|
*--q = i;
|
||||||
|
num /= radix;
|
||||||
|
} while ((divisor /= radix) != 0);
|
||||||
|
|
||||||
|
i = (int)(p + MAX_FILLER - q);
|
||||||
|
do {
|
||||||
|
*p++ = *q++;
|
||||||
|
} while (--i);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg) {
|
||||||
|
int ret;
|
||||||
|
char *p, *s, c, filler;
|
||||||
|
int i, precision, width;
|
||||||
|
bool_t is_long, left_align;
|
||||||
|
long l;
|
||||||
|
#if GFILE_ALLOW_FLOATS
|
||||||
|
float f;
|
||||||
|
char tmpbuf[2*MAX_FILLER + 1];
|
||||||
|
#else
|
||||||
|
char tmpbuf[MAX_FILLER + 1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (maxlen < 0)
|
||||||
|
return 0;
|
||||||
|
if (!maxlen)
|
||||||
|
maxlen = -1;
|
||||||
|
|
||||||
|
while (*fmt) {
|
||||||
|
if (*fmt != '%') {
|
||||||
|
gfileWrite(f, fmt, 1);
|
||||||
|
ret++; if (--maxlen) return ret;
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
p = s = tmpbuf;
|
||||||
|
left_align = FALSE;
|
||||||
|
filler = ' ';
|
||||||
|
width = 0;
|
||||||
|
precision = 0;
|
||||||
|
|
||||||
|
if (*fmt == '-') {
|
||||||
|
fmt++;
|
||||||
|
left_align = TRUE;
|
||||||
|
}
|
||||||
|
if (*fmt == '.') {
|
||||||
|
fmt++;
|
||||||
|
filler = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
c = *fmt++;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
c -= '0';
|
||||||
|
else if (c == '*')
|
||||||
|
c = va_arg(ap, int);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
width = width * 10 + c;
|
||||||
|
}
|
||||||
|
if (c == '.') {
|
||||||
|
while (1) {
|
||||||
|
c = *fmt++;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
c -= '0';
|
||||||
|
else if (c == '*')
|
||||||
|
c = va_arg(ap, int);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
precision = precision * 10 + c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Long modifier.*/
|
||||||
|
if (c == 'l' || c == 'L') {
|
||||||
|
is_long = TRUE;
|
||||||
|
if (*fmt)
|
||||||
|
c = *fmt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
is_long = (c >= 'A') && (c <= 'Z');
|
||||||
|
|
||||||
|
/* Command decoding.*/
|
||||||
|
switch (c) {
|
||||||
|
case 0:
|
||||||
|
return ret;
|
||||||
|
case 'c':
|
||||||
|
filler = ' ';
|
||||||
|
*p++ = va_arg(ap, int);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
filler = ' ';
|
||||||
|
if ((s = va_arg(ap, char *)) == 0)
|
||||||
|
s = "(null)";
|
||||||
|
if (precision == 0)
|
||||||
|
precision = 32767;
|
||||||
|
for (p = s; *p && (--precision >= 0); p++);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
if (is_long)
|
||||||
|
l = va_arg(ap, long);
|
||||||
|
else
|
||||||
|
l = va_arg(ap, int);
|
||||||
|
if (l < 0) {
|
||||||
|
*p++ = '-';
|
||||||
|
l = -l;
|
||||||
|
}
|
||||||
|
p = ltoa_wd(p, l, 10, 0);
|
||||||
|
break;
|
||||||
|
#if GFILE_ALLOW_FLOATS
|
||||||
|
case 'f':
|
||||||
|
f = (float) va_arg(ap, double);
|
||||||
|
if (f < 0) {
|
||||||
|
*p++ = '-';
|
||||||
|
f = -f;
|
||||||
|
}
|
||||||
|
l = f;
|
||||||
|
p = ltoa_wd(p, l, 10, 0);
|
||||||
|
*p++ = '.';
|
||||||
|
l = (f - l) * FLOAT_PRECISION;
|
||||||
|
p = ltoa_wd(p, l, 10, FLOAT_PRECISION / 10);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
c = 16;
|
||||||
|
goto unsigned_common;
|
||||||
|
case 'U':
|
||||||
|
case 'u':
|
||||||
|
c = 10;
|
||||||
|
goto unsigned_common;
|
||||||
|
case 'O':
|
||||||
|
case 'o':
|
||||||
|
c = 8;
|
||||||
|
unsigned_common:
|
||||||
|
if (is_long)
|
||||||
|
l = va_arg(ap, long);
|
||||||
|
else
|
||||||
|
l = va_arg(ap, int);
|
||||||
|
p = ltoa_wd(p, l, c, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*p++ = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = (int)(p - s);
|
||||||
|
if ((width -= i) < 0)
|
||||||
|
width = 0;
|
||||||
|
if (left_align == FALSE)
|
||||||
|
width = -width;
|
||||||
|
if (width < 0) {
|
||||||
|
if (*s == '-' && filler == '0') {
|
||||||
|
gfileWrite(f, s++, 1);
|
||||||
|
ret++; if (--maxlen) return ret;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
gfileWrite(f, &filler, 1);
|
||||||
|
ret++; if (--maxlen) return ret;
|
||||||
|
} while (++width != 0);
|
||||||
|
}
|
||||||
|
while (--i >= 0) {
|
||||||
|
gfileWrite(f, s++, 1);
|
||||||
|
ret++; if (--maxlen) return ret;
|
||||||
|
}
|
||||||
|
while (width) {
|
||||||
|
gfileWrite(f, &filler, 1);
|
||||||
|
ret++; if (--maxlen) return ret;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GFILE_NEED_STRINGS
|
||||||
|
int snprintg(char *buf, int maxlen, const char *fmt, ...) {
|
||||||
|
int res;
|
||||||
|
GFILE f;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (maxlen <= 1) {
|
||||||
|
if (maxlen == 1)
|
||||||
|
*buf = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
|
||||||
|
f.vmt = &StringVMT;
|
||||||
|
f.pos = 0;
|
||||||
|
f.obj = buf;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
res = vfnprintg(&f, maxlen-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
buf[res] = 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg) {
|
||||||
|
int res;
|
||||||
|
GFILE f;
|
||||||
|
|
||||||
|
if (maxlen <= 1) {
|
||||||
|
if (maxlen == 1)
|
||||||
|
*buf = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
|
||||||
|
f.vmt = &StringVMT;
|
||||||
|
f.pos = 0;
|
||||||
|
f.obj = buf;
|
||||||
|
res = vfnprintg(&f, maxlen-1, fmt, arg);
|
||||||
|
buf[res] = 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* scang routines
|
* scang routines
|
||||||
********************************************************/
|
********************************************************/
|
||||||
#if GFILE_NEED_SCANG
|
#if GFILE_NEED_SCANG
|
||||||
|
#error "GFILE-SCANG: Not implemented yet"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* stdio emulation routines
|
* stdio emulation routines
|
||||||
********************************************************/
|
********************************************************/
|
||||||
#ifndef GFILE_NEED_STDIO
|
#if GFILE_NEED_STDIO
|
||||||
#define GFILE_NEED_STDIO FALSE
|
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f) {
|
||||||
|
return gfileRead(f, ptr, size*count)/size;
|
||||||
|
}
|
||||||
|
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f) {
|
||||||
|
return gfileWrite(f, ptr, size*count)/size;
|
||||||
|
}
|
||||||
|
int gstdioSeek(FILE *f, size_t offset, int origin) {
|
||||||
|
switch(origin) {
|
||||||
|
case SEEK_SET:
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
offset += f->pos;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
offset += gfileGetSize(f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return gfileSetPos(f, offset) ? 0 : -1;
|
||||||
|
}
|
||||||
|
int gstdioGetpos(FILE *f, long int *pos) {
|
||||||
|
if (!(f->flags & GFILEFLG_OPEN))
|
||||||
|
return -1;
|
||||||
|
*pos = f->pos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* GFX_USE_GFILE */
|
#endif /* GFX_USE_GFILE */
|
||||||
|
|
|
@ -26,17 +26,19 @@ static bool_t NativeDel(const char *fname);
|
||||||
static bool_t NativeExists(const char *fname);
|
static bool_t NativeExists(const char *fname);
|
||||||
static long int NativeFilesize(const char *fname);
|
static long int NativeFilesize(const char *fname);
|
||||||
static bool_t NativeRen(const char *oldname, const char *newname);
|
static bool_t NativeRen(const char *oldname, const char *newname);
|
||||||
static bool_t NativeOpen(GFILE *f, const char *fname, const char *mode);
|
static bool_t NativeOpen(GFILE *f, const char *fname);
|
||||||
static void NativeClose(GFILE *f);
|
static void NativeClose(GFILE *f);
|
||||||
static int NativeRead(GFILE *f, char *buf, int size);
|
static int NativeRead(GFILE *f, char *buf, int size);
|
||||||
static int NativeWrite(GFILE *f, char *buf, int size);
|
static int NativeWrite(GFILE *f, const char *buf, int size);
|
||||||
static bool_t NativeSetpos(GFILE *f, long int pos);
|
static bool_t NativeSetpos(GFILE *f, long int pos);
|
||||||
static long int NativeGetsize(GFILE *f);
|
static long int NativeGetsize(GFILE *f);
|
||||||
static bool_t NativeEof(GFILE *f);
|
static bool_t NativeEof(GFILE *f);
|
||||||
|
|
||||||
static const GFILEVMT FsNativeVMT = {
|
static const GFILEVMT FsNativeVMT = {
|
||||||
GFILE_CHAINHEAD, // next
|
GFILE_CHAINHEAD, // next
|
||||||
#if !defined(WIN32) && !GFX_USE_OS_WIN32
|
#if defined(WIN32) || GFX_USE_OS_WIN32
|
||||||
|
GFSFLG_TEXTMODES|
|
||||||
|
#else
|
||||||
GFSFLG_CASESENSITIVE|
|
GFSFLG_CASESENSITIVE|
|
||||||
#endif
|
#endif
|
||||||
GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
|
GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
|
||||||
|
@ -84,11 +86,9 @@ static bool_t NativeOpen(GFILE *f, const char *fname) {
|
||||||
}
|
}
|
||||||
static void NativeClose(GFILE *f) { fclose((FILE *)f->obj); }
|
static void NativeClose(GFILE *f) { fclose((FILE *)f->obj); }
|
||||||
static int NativeRead(GFILE *f, char *buf, int size) { return fread(buf, 1, size, (FILE *)f->obj); }
|
static int NativeRead(GFILE *f, char *buf, int size) { return fread(buf, 1, size, (FILE *)f->obj); }
|
||||||
static int NativeWrite(GFILE *f, char *buf, int size) { return fwrite(buf, 1, size, (FILE *)f->obj); }
|
static int NativeWrite(GFILE *f, const char *buf, int size) { return fwrite(buf, 1, size, (FILE *)f->obj); }
|
||||||
static bool_t NativeSetpos(GFILE *f, long int pos) {
|
static bool_t NativeSetpos(GFILE *f, long int pos) {
|
||||||
if (fseek((FILE *)f->obj, pos, SEEK_SET)) return FALSE;
|
return fseek((FILE *)f->obj, pos, SEEK_SET) ? FALSE : TRUE;
|
||||||
f->pos = pos;
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
static long int NativeGetsize(GFILE *f) {
|
static long int NativeGetsize(GFILE *f) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
@ -30,7 +30,7 @@ static const ROMFS_DIRENTRY const *FsROMHead = ROMFS_DIRENTRY_HEAD;
|
||||||
|
|
||||||
static bool_t ROMExists(const char *fname);
|
static bool_t ROMExists(const char *fname);
|
||||||
static long int ROMFilesize(const char *fname);
|
static long int ROMFilesize(const char *fname);
|
||||||
static bool_t ROMOpen(GFILE *f, const char *fname, const char *mode);
|
static bool_t ROMOpen(GFILE *f, const char *fname);
|
||||||
static void ROMClose(GFILE *f);
|
static void ROMClose(GFILE *f);
|
||||||
static int ROMRead(GFILE *f, char *buf, int size);
|
static int ROMRead(GFILE *f, char *buf, int size);
|
||||||
static bool_t ROMSetpos(GFILE *f, long int pos);
|
static bool_t ROMSetpos(GFILE *f, long int pos);
|
||||||
|
|
Loading…
Add table
Reference in a new issue