all repos — mgba @ 6f628526710a02d29d9f6dea1f515e21d8981184

mGBA Game Boy Advance Emulator

VFS: More VFile memory interfaces
Jeffrey Pfau jeffrey@endrift.com
Sat, 02 Jan 2016 17:07:44 -0800
commit

6f628526710a02d29d9f6dea1f515e21d8981184

parent

d662ba98de41c22489ca4d42ae3291fe043aa13e

2 files changed, 150 insertions(+), 0 deletions(-)

jump to
M src/util/vfs.hsrc/util/vfs.h

@@ -67,6 +67,8 @@ struct VFile* VFileOpenFD(const char* path, int flags);

struct VFile* VFileFOpen(const char* path, const char* mode); struct VFile* VFileFromFD(int fd); 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 VDir* VDirOpen(const char* path);
M src/util/vfs/vfs-mem.csrc/util/vfs/vfs-mem.c

@@ -4,6 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public

* 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/. */ #include "util/vfs.h" +#include "util/memory.h" struct VFileMem { struct VFile d;

@@ -13,12 +14,17 @@ size_t offset;

}; 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 _vfmSeekExpanding(struct VFile* vf, off_t offset, int whence); 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 _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 _vfmUnmap(struct VFile* vf, void* memory, 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 bool _vfmSync(struct VFile* vf, const void* buffer, size_t size);

@@ -42,6 +48,63 @@ vfm->d.readline = VFileReadline;

vfm->d.write = _vfmWrite; 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* 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.size = _vfmSize; vfm->d.sync = _vfmSync;

@@ -49,6 +112,16 @@

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) { struct VFileMem* vfm = (struct VFileMem*) vf; vfm->mem = 0;

@@ -56,12 +129,23 @@ free(vfm);

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) { 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:

@@ -88,6 +172,41 @@ vfm->offset = 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) { struct VFileMem* vfm = (struct VFileMem*) vf;

@@ -112,6 +231,26 @@ vfm->offset += 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) { struct VFileMem* vfm = (struct VFileMem*) vf;

@@ -130,6 +269,15 @@ UNUSED(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? UNUSED(vf); UNUSED(size);