all repos — mgba @ d957736ed95751328f6913b1954cdeac0bf7e80d

mGBA Game Boy Advance Emulator

src/util/vfs/vfs-mem.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "util/vfs.h"
  7
  8struct VFileMem {
  9	struct VFile d;
 10	void* mem;
 11	size_t size;
 12	size_t offset;
 13};
 14
 15static bool _vfmClose(struct VFile* vf);
 16static off_t _vfmSeek(struct VFile* vf, off_t offset, int whence);
 17static ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size);
 18static ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size);
 19static void* _vfmMap(struct VFile* vf, size_t size, int flags);
 20static void _vfmUnmap(struct VFile* vf, void* memory, size_t size);
 21static void _vfmTruncate(struct VFile* vf, size_t size);
 22static ssize_t _vfmSize(struct VFile* vf);
 23
 24struct VFile* VFileFromMemory(void* mem, size_t size) {
 25	if (!mem || !size) {
 26		return 0;
 27	}
 28
 29	struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
 30	if (!vfm) {
 31		return 0;
 32	}
 33
 34	vfm->mem = mem;
 35	vfm->size = size;
 36	vfm->offset = 0;
 37	vfm->d.close = _vfmClose;
 38	vfm->d.seek = _vfmSeek;
 39	vfm->d.read = _vfmRead;
 40	vfm->d.readline = VFileReadline;
 41	vfm->d.write = _vfmWrite;
 42	vfm->d.map = _vfmMap;
 43	vfm->d.unmap = _vfmUnmap;
 44	vfm->d.truncate = _vfmTruncate;
 45	vfm->d.size = _vfmSize;
 46
 47	return &vfm->d;
 48}
 49
 50bool _vfmClose(struct VFile* vf) {
 51	struct VFileMem* vfm = (struct VFileMem*) vf;
 52	vfm->mem = 0;
 53	free(vfm);
 54	return true;
 55}
 56
 57off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
 58	struct VFileMem* vfm = (struct VFileMem*) vf;
 59
 60	size_t position;
 61	switch (whence) {
 62	case SEEK_SET:
 63		position = offset;
 64		break;
 65	case SEEK_CUR:
 66		if (offset < 0 && ((vfm->offset < (size_t) -offset) || (offset == INT_MIN))) {
 67			return -1;
 68		}
 69		position = vfm->offset + offset;
 70		break;
 71	case SEEK_END:
 72		if (offset < 0 && ((vfm->size < (size_t) -offset) || (offset == INT_MIN))) {
 73			return -1;
 74		}
 75		position = vfm->size + offset;
 76		break;
 77	default:
 78		return -1;
 79	}
 80
 81	if (position > vfm->size) {
 82		return -1;
 83	}
 84
 85	vfm->offset = position;
 86	return position;
 87}
 88
 89ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
 90	struct VFileMem* vfm = (struct VFileMem*) vf;
 91
 92	if (size + vfm->offset >= vfm->size) {
 93		size = vfm->size - vfm->offset;
 94	}
 95
 96	memcpy(buffer, (void*) ((uintptr_t) vfm->mem + vfm->offset), size);
 97	vfm->offset += size;
 98	return size;
 99}
100
101ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size) {
102	struct VFileMem* vfm = (struct VFileMem*) vf;
103
104	if (size + vfm->offset >= vfm->size) {
105		size = vfm->size - vfm->offset;
106	}
107
108	memcpy((void*) ((uintptr_t) vfm->mem + vfm->offset), buffer, size);
109	vfm->offset += size;
110	return size;
111}
112
113void* _vfmMap(struct VFile* vf, size_t size, int flags) {
114	struct VFileMem* vfm = (struct VFileMem*) vf;
115
116	UNUSED(flags);
117	if (size > vfm->size) {
118		return 0;
119	}
120
121	return vfm->mem;
122}
123
124void _vfmUnmap(struct VFile* vf, void* memory, size_t size) {
125	UNUSED(vf);
126	UNUSED(memory);
127	UNUSED(size);
128}
129
130void _vfmTruncate(struct VFile* vf, size_t size) {
131	// TODO: Return value?
132	UNUSED(vf);
133	UNUSED(size);
134}
135
136ssize_t _vfmSize(struct VFile* vf) {
137	struct VFileMem* vfm = (struct VFileMem*) vf;
138	return vfm->size;
139}