all repos — mgba @ e17e4fd19003209ff9db1f0ac1394e463c7b4a47

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);
 23static bool _vfmSync(struct VFile* vf, const void* buffer, size_t size);
 24
 25struct VFile* VFileFromMemory(void* mem, size_t size) {
 26	if (!mem || !size) {
 27		return 0;
 28	}
 29
 30	struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
 31	if (!vfm) {
 32		return 0;
 33	}
 34
 35	vfm->mem = mem;
 36	vfm->size = size;
 37	vfm->offset = 0;
 38	vfm->d.close = _vfmClose;
 39	vfm->d.seek = _vfmSeek;
 40	vfm->d.read = _vfmRead;
 41	vfm->d.readline = VFileReadline;
 42	vfm->d.write = _vfmWrite;
 43	vfm->d.map = _vfmMap;
 44	vfm->d.unmap = _vfmUnmap;
 45	vfm->d.truncate = _vfmTruncate;
 46	vfm->d.size = _vfmSize;
 47	vfm->d.sync = _vfmSync;
 48
 49	return &vfm->d;
 50}
 51
 52bool _vfmClose(struct VFile* vf) {
 53	struct VFileMem* vfm = (struct VFileMem*) vf;
 54	vfm->mem = 0;
 55	free(vfm);
 56	return true;
 57}
 58
 59off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
 60	struct VFileMem* vfm = (struct VFileMem*) vf;
 61
 62	size_t position;
 63	switch (whence) {
 64	case SEEK_SET:
 65		position = offset;
 66		break;
 67	case SEEK_CUR:
 68		if (offset < 0 && ((vfm->offset < (size_t) -offset) || (offset == INT_MIN))) {
 69			return -1;
 70		}
 71		position = vfm->offset + offset;
 72		break;
 73	case SEEK_END:
 74		if (offset < 0 && ((vfm->size < (size_t) -offset) || (offset == INT_MIN))) {
 75			return -1;
 76		}
 77		position = vfm->size + offset;
 78		break;
 79	default:
 80		return -1;
 81	}
 82
 83	if (position > vfm->size) {
 84		return -1;
 85	}
 86
 87	vfm->offset = position;
 88	return position;
 89}
 90
 91ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
 92	struct VFileMem* vfm = (struct VFileMem*) vf;
 93
 94	if (size + vfm->offset >= vfm->size) {
 95		size = vfm->size - vfm->offset;
 96	}
 97
 98	memcpy(buffer, (void*) ((uintptr_t) vfm->mem + vfm->offset), size);
 99	vfm->offset += size;
100	return size;
101}
102
103ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size) {
104	struct VFileMem* vfm = (struct VFileMem*) vf;
105
106	if (size + vfm->offset >= vfm->size) {
107		size = vfm->size - vfm->offset;
108	}
109
110	memcpy((void*) ((uintptr_t) vfm->mem + vfm->offset), buffer, size);
111	vfm->offset += size;
112	return size;
113}
114
115void* _vfmMap(struct VFile* vf, size_t size, int flags) {
116	struct VFileMem* vfm = (struct VFileMem*) vf;
117
118	UNUSED(flags);
119	if (size > vfm->size) {
120		return 0;
121	}
122
123	return vfm->mem;
124}
125
126void _vfmUnmap(struct VFile* vf, void* memory, size_t size) {
127	UNUSED(vf);
128	UNUSED(memory);
129	UNUSED(size);
130}
131
132void _vfmTruncate(struct VFile* vf, size_t size) {
133	// TODO: Return value?
134	UNUSED(vf);
135	UNUSED(size);
136}
137
138ssize_t _vfmSize(struct VFile* vf) {
139	struct VFileMem* vfm = (struct VFileMem*) vf;
140	return vfm->size;
141}
142
143bool _vfmSync(struct VFile* vf, const void* buffer, size_t size) {
144	UNUSED(vf);
145	UNUSED(buffer);
146	UNUSED(size);
147	return true;
148}