mirror of
https://github.com/libretro/mgba.git
synced 2024-12-01 04:00:32 +00:00
Util: VFile backed by memory
This commit is contained in:
parent
9adfcad1b5
commit
e61d413d69
@ -38,6 +38,7 @@ struct VDir {
|
||||
|
||||
struct VFile* VFileOpen(const char* path, int flags);
|
||||
struct VFile* VFileFromFD(int fd);
|
||||
struct VFile* VFileFromMemory(void* mem, size_t size);
|
||||
|
||||
struct VDir* VDirOpen(const char* path);
|
||||
|
||||
|
139
src/util/vfs/vfs-mem.c
Normal file
139
src/util/vfs/vfs-mem.c
Normal file
@ -0,0 +1,139 @@
|
||||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* 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"
|
||||
|
||||
struct VFileMem {
|
||||
struct VFile d;
|
||||
void* mem;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
static bool _vfmClose(struct VFile* vf);
|
||||
static off_t _vfmSeek(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 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 ssize_t _vfmSize(struct VFile* vf);
|
||||
|
||||
struct VFile* VFileFromMemory(void* mem, size_t size) {
|
||||
if (!mem || !size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
|
||||
if (!vfm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfm->mem = 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 = _vfmWrite;
|
||||
vfm->d.map = _vfmMap;
|
||||
vfm->d.unmap = _vfmUnmap;
|
||||
vfm->d.truncate = _vfmTruncate;
|
||||
vfm->d.size = _vfmSize;
|
||||
|
||||
return &vfm->d;
|
||||
}
|
||||
|
||||
bool _vfmClose(struct VFile* vf) {
|
||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||
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:
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
vfm->offset = position;
|
||||
return position;
|
||||
}
|
||||
|
||||
ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
|
||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||
|
||||
if (size + vfm->offset >= vfm->size) {
|
||||
size = vfm->size - vfm->offset;
|
||||
}
|
||||
|
||||
memcpy(buffer, vfm->mem + vfm->offset, size);
|
||||
vfm->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size) {
|
||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||
|
||||
if (size + vfm->offset >= vfm->size) {
|
||||
size = vfm->size - vfm->offset;
|
||||
}
|
||||
|
||||
memcpy(vfm->mem + vfm->offset, buffer, size);
|
||||
vfm->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
void* _vfmMap(struct VFile* vf, size_t size, int flags) {
|
||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||
|
||||
UNUSED(flags);
|
||||
if (size > vfm->size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vfm->mem;
|
||||
}
|
||||
|
||||
void _vfmUnmap(struct VFile* vf, void* memory, size_t size) {
|
||||
UNUSED(vf);
|
||||
UNUSED(memory);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void _vfmTruncate(struct VFile* vf, size_t size) {
|
||||
// TODO: Return value?
|
||||
UNUSED(vf);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
ssize_t _vfmSize(struct VFile* vf) {
|
||||
struct VFileMem* vfm = (struct VFileMem*) vf;
|
||||
return vfm->size;
|
||||
}
|
Loading…
Reference in New Issue
Block a user