More code for GFile

ugfx_release_2.6
inmarket 2014-01-24 19:33:28 +10:00
parent 0d9532c047
commit c5ab2adbf0
4 changed files with 128 additions and 38 deletions

View File

@ -34,13 +34,17 @@
typedef struct GFILE {
const struct GFILEVMT * vmt;
uint16_t flags;
#define GFILEFLG_OPEN 0x0001
#define GFILEFLG_READ 0x0002
#define GFILEFLG_WRITE 0x0004
#define GFILEFLG_APPEND 0x0008
#define GFILEFLG_CANSEEK 0x0010
#define GFILEFLG_DELONCLOSE 0x0020
#define GFILEFLG_FAILONBLOCK 0x0040
#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
short err;
void * obj;
long int pos;
@ -48,18 +52,18 @@ typedef struct GFILE {
typedef struct GFILEVMT {
const struct GFILEVMT * next;
char prefix;
uint16_t flags;
uint8_t flags;
#define GFSFLG_WRITEABLE 0x0001
#define GFSFLG_CASESENSITIVE 0x0002
#define GFSFLG_SEEKABLE 0x0004
#define GFSFLG_FAST 0x0010
#define GFSFLG_SMALL 0x0020
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, const char *mode);
bool_t open(GFILE *f, const char *fname);
void close(GFILE *f);
int read(GFILE *f, char *buf, int size);
int write(GFILE *f, char *buf, int size);
@ -104,16 +108,6 @@ extern GFILE *gfileStdOut;
//ungetc
//void perror (const char * str);
//"r" read: Open file for input operations. The file must exist.
//"w" write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file.
//"a" append: Open file for output at the end of a file. Output operations always write data at the end of the file, expanding it. Repositioning operations (fseek, fsetpos, rewind) are ignored. The file is created if it does not exist.
//"r+" read/update: Open a file for update (both for input and output). The file must exist.
//"w+" write/update: Create an empty file and open it for update (both for input and output). If a file with the same name already exists its contents are discarded and the file is treated as a new empty file.
//"a+" append/update: Open a file for update (both for input and output) with all output operations writing data at the end of the file. Repositioning operations (fseek, fsetpos, rewind) affects the next input operations, but output operations move the position back to the end of file. The file is created if it does not exist.
//"...b" A binary stream
//"...x" Added to "w" - fail if file exists
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -147,7 +147,7 @@ long int gfileGetFilesize(const char *fname) {
bool_t gfileRename(const char *oldname, const char *newname) {
const GFILEVMT *p;
if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1])) {
if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) {
char ch;
if (oldname[0] && oldname[1] == '|') {
@ -155,6 +155,7 @@ bool_t gfileRename(const char *oldname, const char *newname) {
oldname += 2;
if (newname[0] && newname[1] == '|') {
if (newname[0] != ch)
// Both oldname and newname are fs specific but different ones.
return FALSE;
newname += 2;
}
@ -175,12 +176,100 @@ bool_t gfileRename(const char *oldname, const char *newname) {
return FALSE;
}
GFILE *gfileOpen(const char *fname, const char *mode) {
static uint16_t mode2flags(const char *mode) {
uint16_t flags;
switch(mode[0]) {
case 'r':
flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST;
while (*++mode) {
switch(mode[0]) {
case '+': flags |= GFILEFLG_WRITE; break;
case 'b': flags |= GFILEFLG_BINARY; break;
}
}
return flags;
case 'w':
flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
while (*++mode) {
switch(mode[0]) {
case '+': flags |= GFILEFLG_READ; break;
case 'b': flags |= GFILEFLG_BINARY; break;
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
return flags;
case 'a':
flags = GFILEFLG_WRITE|GFILEFLG_APPEND;
while (*++mode) {
switch(mode[0]) {
case '+': flags |= GFILEFLG_READ; break;
case 'b': flags |= GFILEFLG_BINARY; break;
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
}
}
return flags;
}
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))
return FALSE;
// Try to open
if (!p->open || !p->open(f, fname))
return FALSE;
// File is open - fill in all the details
f->vmt = p;
f->err = 0;
f->pos = 0;
f->flags |= GFILEFLG_OPEN;
if (p->flags & GFSFLG_SEEKABLE)
f->flags |= GFILEFLG_CANSEEK;
return TRUE;
}
GFILE *gfileOpen(const char *fname, const char *mode) {
GFILE *f;
const GFILEVMT *p;
// First find an available GFILE slot.
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
if (!(f->flags & GFILEFLG_OPEN)) {
// Get the requested mode
if (!(f->flags = mode2flags(mode)))
return FALSE;
// Try to open the file
if (fname[0] && fname[1] == '|') {
for(p = FsChain; p; p = p->next) {
if (p->prefix == fname[0])
return testopen(p, f, fname+2);
}
} else {
for(p = FsChain; p; p = p->next) {
if (testopen(p, f, fname))
return TRUE;
}
}
// File not found
return FALSE;
}
}
// No available slot
return FALSE;
}
void gfileClose(GFILE *f) {
// Make sure it is one of the system GFILE's
if (f < gfileArr || f >= &gfileArr[GFILE_MAX_GFILES])
return;
}
size_t gfileRead(GFILE *f, char *buf, size_t len) {

View File

@ -36,11 +36,11 @@ static bool_t NativeEof(GFILE *f);
static const GFILEVMT FsNativeVMT = {
GFILE_CHAINHEAD, // next
'N', // prefix
#if !defined(WIN32) && !GFX_USE_OS_WIN32
GFSFLG_CASESENSITIVE|
#endif
GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
'N', // prefix
NativeDel, NativeExists, NativeFilesize, NativeRen,
NativeOpen, NativeClose, NativeRead, NativeWrite,
NativeSetpos, NativeGetsize, NativeEof,
@ -48,6 +48,23 @@ static const GFILEVMT FsNativeVMT = {
#undef GFILE_CHAINHEAD
#define GFILE_CHAINHEAD &FsNativeVMT
static char *flags2mode(char *buf, uint16_t flags) {
if (flags & GFILEFLG_MUSTEXIST)
*buf = 'r';
else if (flags & GFILEFLG_APPEND)
*buf = 'a';
else
*buf = 'w';
buf++;
if ((flags & (GFILEFLG_READ|GFILEFLG_WRITE)) == (GFILEFLG_READ|GFILEFLG_WRITE))
*buf++ = '+';
if (flags & GFILEFLG_BINARY)
*buf++ = 'b';
if (flags & GFILEFLG_MUSTNOTEXIST)
*buf++ = 'x';
*buf++ = 0;
}
static bool_t NativeDel(const char *fname) { return remove(fname) ? FALSE : TRUE; }
static bool_t NativeExists(const char *fname) { return access(fname, 0) ? FALSE : TRUE; }
static long int NativeFilesize(const char *fname) {
@ -56,12 +73,12 @@ static long int NativeFilesize(const char *fname) {
return st.st_size;
}
static bool_t NativeRen(const char *oldname, const char *newname) { return rename(oldname, newname) ? FALSE : TRUE };
static bool_t NativeOpen(GFILE *f, const char *fname, const char *mode) {
static bool_t NativeOpen(GFILE *f, const char *fname) {
FILE *fd;
char mode[5];
if (!(fd = fopen(fname, mode)))
return FALSE;
f->vmt = &FsNativeVMT;
f->obj = (void *)fd;
return TRUE;
}

View File

@ -39,8 +39,8 @@ static bool_t ROMEof(GFILE *f);
static const GFILEVMT FsROMVMT = {
GFILE_CHAINHEAD, // next
'S', // prefix
GFSFLG_CASESENSITIVE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
'S', // prefix
0, ROMExists, ROMFilesize, 0,
ROMOpen, ROMClose, ROMRead, 0,
ROMSetpos, ROMGetsize, ROMEof,
@ -64,20 +64,10 @@ static long int ROMFilesize(const char *fname) {
if (!(p = ROMFindFile(fname))) return -1;
return p->size;
}
static bool_t ROMOpen(GFILE *f, const char *fname, const char *mode) {
static bool_t ROMOpen(GFILE *f, const char *fname) {
const ROMFS_DIRENTRY *p;
// Check mode
if (mode[0] != 'r') return FALSE;
while(*++mode) {
switch(*mode) {
case '+': case 'w': case 'a':
return FALSE;
}
}
if (!(p = ROMFindFile(fname))) return FALSE;
f->vmt = &FsROMVMT;
f->obj = (void *)p;
return TRUE;
}