mirror of https://github.com/mgba-emu/mgba.git
VFS: More VFile memory interfaces
This commit is contained in:
parent
d662ba98de
commit
6f62852671
|
@ -67,6 +67,8 @@ struct VFile* VFileOpenFD(const char* path, int flags);
|
||||||
struct VFile* VFileFOpen(const char* path, const char* mode);
|
struct VFile* VFileFOpen(const char* path, const char* mode);
|
||||||
struct VFile* VFileFromFD(int fd);
|
struct VFile* VFileFromFD(int fd);
|
||||||
struct VFile* VFileFromMemory(void* mem, size_t size);
|
struct VFile* VFileFromMemory(void* mem, size_t size);
|
||||||
|
struct VFile* VFileFromConstMemory(const void* mem, size_t size);
|
||||||
|
struct VFile* VFileMemChunk(const void* mem, size_t size);
|
||||||
struct VFile* VFileFromFILE(FILE* file);
|
struct VFile* VFileFromFILE(FILE* file);
|
||||||
|
|
||||||
struct VDir* VDirOpen(const char* path);
|
struct VDir* VDirOpen(const char* path);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "util/vfs.h"
|
#include "util/vfs.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
struct VFileMem {
|
struct VFileMem {
|
||||||
struct VFile d;
|
struct VFile d;
|
||||||
|
@ -13,12 +14,17 @@ struct VFileMem {
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _vfmClose(struct VFile* vf);
|
static bool _vfmClose(struct VFile* vf);
|
||||||
|
static bool _vfmCloseFree(struct VFile* vf);
|
||||||
static off_t _vfmSeek(struct VFile* vf, off_t offset, int whence);
|
static off_t _vfmSeek(struct VFile* vf, off_t offset, int whence);
|
||||||
|
static off_t _vfmSeekExpanding(struct VFile* vf, off_t offset, int whence);
|
||||||
static ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size);
|
static ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size);
|
||||||
static ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size);
|
static ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size);
|
||||||
|
static ssize_t _vfmWriteExpanding(struct VFile* vf, const void* buffer, size_t size);
|
||||||
|
static ssize_t _vfmWriteNoop(struct VFile* vf, const void* buffer, size_t size);
|
||||||
static void* _vfmMap(struct VFile* vf, size_t size, int flags);
|
static void* _vfmMap(struct VFile* vf, size_t size, int flags);
|
||||||
static void _vfmUnmap(struct VFile* vf, void* memory, size_t size);
|
static void _vfmUnmap(struct VFile* vf, void* memory, size_t size);
|
||||||
static void _vfmTruncate(struct VFile* vf, size_t size);
|
static void _vfmTruncate(struct VFile* vf, size_t size);
|
||||||
|
static void _vfmTruncateNoop(struct VFile* vf, size_t size);
|
||||||
static ssize_t _vfmSize(struct VFile* vf);
|
static ssize_t _vfmSize(struct VFile* vf);
|
||||||
static bool _vfmSync(struct VFile* vf, const void* buffer, size_t size);
|
static bool _vfmSync(struct VFile* vf, const void* buffer, size_t size);
|
||||||
|
|
||||||
|
@ -42,6 +48,63 @@ struct VFile* VFileFromMemory(void* mem, size_t size) {
|
||||||
vfm->d.write = _vfmWrite;
|
vfm->d.write = _vfmWrite;
|
||||||
vfm->d.map = _vfmMap;
|
vfm->d.map = _vfmMap;
|
||||||
vfm->d.unmap = _vfmUnmap;
|
vfm->d.unmap = _vfmUnmap;
|
||||||
|
vfm->d.truncate = _vfmTruncateNoop;
|
||||||
|
vfm->d.size = _vfmSize;
|
||||||
|
vfm->d.sync = _vfmSync;
|
||||||
|
|
||||||
|
return &vfm->d;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VFile* VFileFromConstMemory(const void* mem, size_t size) {
|
||||||
|
if (!mem || !size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
|
||||||
|
if (!vfm) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfm->mem = (void*) mem;
|
||||||
|
vfm->size = size;
|
||||||
|
vfm->offset = 0;
|
||||||
|
vfm->d.close = _vfmClose;
|
||||||
|
vfm->d.seek = _vfmSeek;
|
||||||
|
vfm->d.read = _vfmRead;
|
||||||
|
vfm->d.readline = VFileReadline;
|
||||||
|
vfm->d.write = _vfmWriteNoop;
|
||||||
|
vfm->d.map = _vfmMap;
|
||||||
|
vfm->d.unmap = _vfmUnmap;
|
||||||
|
vfm->d.truncate = _vfmTruncateNoop;
|
||||||
|
vfm->d.size = _vfmSize;
|
||||||
|
vfm->d.sync = _vfmSync;
|
||||||
|
|
||||||
|
return &vfm->d;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VFile* VFileMemChunk(const void* mem, size_t size) {
|
||||||
|
struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
|
||||||
|
if (!vfm) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfm->size = size;
|
||||||
|
if (size) {
|
||||||
|
vfm->mem = anonymousMemoryMap(size);
|
||||||
|
if (mem) {
|
||||||
|
memcpy(vfm->mem, mem, size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vfm->mem = 0;
|
||||||
|
}
|
||||||
|
vfm->offset = 0;
|
||||||
|
vfm->d.close = _vfmCloseFree;
|
||||||
|
vfm->d.seek = _vfmSeekExpanding;
|
||||||
|
vfm->d.read = _vfmRead;
|
||||||
|
vfm->d.readline = VFileReadline;
|
||||||
|
vfm->d.write = _vfmWriteExpanding;
|
||||||
|
vfm->d.map = _vfmMap;
|
||||||
|
vfm->d.unmap = _vfmUnmap;
|
||||||
vfm->d.truncate = _vfmTruncate;
|
vfm->d.truncate = _vfmTruncate;
|
||||||
vfm->d.size = _vfmSize;
|
vfm->d.size = _vfmSize;
|
||||||
vfm->d.sync = _vfmSync;
|
vfm->d.sync = _vfmSync;
|
||||||
|
@ -49,6 +112,16 @@ struct VFile* VFileFromMemory(void* mem, size_t size) {
|
||||||
return &vfm->d;
|
return &vfm->d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _vfmExpand(struct VFileMem* vfm, size_t newSize) {
|
||||||
|
void* oldBuf = vfm->mem;
|
||||||
|
vfm->mem = anonymousMemoryMap(newSize);
|
||||||
|
if (oldBuf) {
|
||||||
|
memcpy(vfm->mem, oldBuf, vfm->size);
|
||||||
|
mappedMemoryFree(oldBuf, vfm->size);
|
||||||
|
}
|
||||||
|
vfm->size = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool _vfmClose(struct VFile* vf) {
|
bool _vfmClose(struct VFile* vf) {
|
||||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
vfm->mem = 0;
|
vfm->mem = 0;
|
||||||
|
@ -56,12 +129,23 @@ bool _vfmClose(struct VFile* vf) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _vfmCloseFree(struct VFile* vf) {
|
||||||
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
mappedMemoryFree(vfm->mem, vfm->size);
|
||||||
|
vfm->mem = 0;
|
||||||
|
free(vfm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
|
off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
|
||||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
|
||||||
size_t position;
|
size_t position;
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
|
if (offset < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
position = offset;
|
position = offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
|
@ -88,6 +172,41 @@ off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
off_t _vfmSeekExpanding(struct VFile* vf, off_t offset, int whence) {
|
||||||
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
|
||||||
|
size_t position;
|
||||||
|
switch (whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
if (offset < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
position = offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
if (offset < 0 && ((vfm->offset < (size_t) -offset) || (offset == INT_MIN))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
position = vfm->offset + offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
if (offset < 0 && ((vfm->size < (size_t) -offset) || (offset == INT_MIN))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
position = vfm->size + offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position > vfm->size) {
|
||||||
|
_vfmExpand(vfm, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfm->offset = position;
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
|
ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
|
||||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
|
||||||
|
@ -112,6 +231,26 @@ ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size) {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t _vfmWriteExpanding(struct VFile* vf, const void* buffer, size_t size) {
|
||||||
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
|
||||||
|
if (size + vfm->offset >= vfm->size) {
|
||||||
|
_vfmExpand(vfm, vfm->offset + size);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void*) ((uintptr_t) vfm->mem + vfm->offset), buffer, size);
|
||||||
|
vfm->offset += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t _vfmWriteNoop(struct VFile* vf, const void* buffer, size_t size) {
|
||||||
|
UNUSED(vf);
|
||||||
|
UNUSED(buffer);
|
||||||
|
UNUSED(size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void* _vfmMap(struct VFile* vf, size_t size, int flags) {
|
void* _vfmMap(struct VFile* vf, size_t size, int flags) {
|
||||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
|
||||||
|
@ -130,6 +269,15 @@ void _vfmUnmap(struct VFile* vf, void* memory, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _vfmTruncate(struct VFile* vf, size_t size) {
|
void _vfmTruncate(struct VFile* vf, size_t size) {
|
||||||
|
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||||
|
if (size > vfm->size) {
|
||||||
|
_vfmExpand(vfm, size);
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _vfmTruncateNoop(struct VFile* vf, size_t size) {
|
||||||
// TODO: Return value?
|
// TODO: Return value?
|
||||||
UNUSED(vf);
|
UNUSED(vf);
|
||||||
UNUSED(size);
|
UNUSED(size);
|
||||||
|
|
Loading…
Reference in New Issue