all repos — mgba @ b54f5a997a493f977d77a8273ff95b266d9abe7e

mGBA Game Boy Advance Emulator

src/util/vfs/vfs-file.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
  8#include "util/memory.h"
  9
 10#include <stdio.h>
 11
 12struct VFileFILE {
 13	struct VFile d;
 14	FILE* file;
 15};
 16
 17static bool _vffClose(struct VFile* vf);
 18static off_t _vffSeek(struct VFile* vf, off_t offset, int whence);
 19static ssize_t _vffRead(struct VFile* vf, void* buffer, size_t size);
 20static ssize_t _vffWrite(struct VFile* vf, const void* buffer, size_t size);
 21static void* _vffMap(struct VFile* vf, size_t size, int flags);
 22static void _vffUnmap(struct VFile* vf, void* memory, size_t size);
 23static void _vffTruncate(struct VFile* vf, size_t size);
 24static ssize_t _vffSize(struct VFile* vf);
 25
 26struct VFile* VFileFOpen(const char* path, const char* mode) {
 27	if (!path && !mode) {
 28		return 0;
 29	}
 30	FILE* file = fopen(path, mode);
 31	return VFileFromFILE(file);
 32}
 33
 34struct VFile* VFileFromFILE(FILE* file) {
 35	if (!file) {
 36		return 0;
 37	}
 38
 39	struct VFileFILE* vff = malloc(sizeof(struct VFileFILE));
 40	if (!vff) {
 41		return 0;
 42	}
 43
 44	vff->file = file;
 45	vff->d.close = _vffClose;
 46	vff->d.seek = _vffSeek;
 47	vff->d.read = _vffRead;
 48	vff->d.readline = VFileReadline;
 49	vff->d.write = _vffWrite;
 50	vff->d.map = _vffMap;
 51	vff->d.unmap = _vffUnmap;
 52	vff->d.truncate = _vffTruncate;
 53	vff->d.size = _vffSize;
 54
 55	return &vff->d;
 56}
 57
 58bool _vffClose(struct VFile* vf) {
 59	struct VFileFILE* vff = (struct VFileFILE*) vf;
 60	if (fclose(vff->file) < 0) {
 61		return false;
 62	}
 63	free(vff);
 64	return true;
 65}
 66
 67off_t _vffSeek(struct VFile* vf, off_t offset, int whence) {
 68	struct VFileFILE* vff = (struct VFileFILE*) vf;
 69	return fseek(vff->file, offset, whence);
 70}
 71
 72ssize_t _vffRead(struct VFile* vf, void* buffer, size_t size) {
 73	struct VFileFILE* vff = (struct VFileFILE*) vf;
 74	return fread(buffer, size, 1, vff->file);
 75}
 76
 77ssize_t _vffWrite(struct VFile* vf, const void* buffer, size_t size) {
 78	struct VFileFILE* vff = (struct VFileFILE*) vf;
 79	return fwrite(buffer, size, 1, vff->file);
 80}
 81
 82static void* _vffMap(struct VFile* vf, size_t size, int flags) {
 83	UNUSED(flags);
 84	struct VFileFILE* vff = (struct VFileFILE*) vf;
 85	void* mem = anonymousMemoryMap(size);
 86	if (!mem) {
 87		return 0;
 88	}
 89	long pos = ftell(vff->file);
 90	fseek(vff->file, 0, SEEK_SET);
 91	fread(mem, size, 1, vff->file);
 92	fseek(vff->file, pos, SEEK_SET);
 93	return mem;
 94}
 95
 96static void _vffUnmap(struct VFile* vf, void* memory, size_t size) {
 97	struct VFileFILE* vff = (struct VFileFILE*) vf;
 98	long pos = ftell(vff->file);
 99	fseek(vff->file, 0, SEEK_SET);
100	fwrite(memory, size, 1, vff->file);
101	fseek(vff->file, pos, SEEK_SET);
102	mappedMemoryFree(memory, size);
103}
104
105static void _vffTruncate(struct VFile* vf, size_t size) {
106	struct VFileFILE* vff = (struct VFileFILE*) vf;
107	long pos = ftell(vff->file);
108	fseek(vff->file, 0, SEEK_END);
109	ssize_t realSize = ftell(vff->file);
110	if (realSize < 0) {
111		return;
112	}
113	while (size > (size_t) realSize) {
114		static const char zeros[128] = "";
115		size_t diff = size - realSize;
116		if (diff > sizeof(zeros)) {
117			diff = sizeof(zeros);
118		}
119		fwrite(zeros, diff, 1, vff->file);
120		realSize += diff;
121	}
122	fseek(vff->file, pos, SEEK_SET);
123}
124
125static ssize_t _vffSize(struct VFile* vf) {
126	struct VFileFILE* vff = (struct VFileFILE*) vf;
127	long pos = ftell(vff->file);
128	fseek(vff->file, 0, SEEK_END);
129	ssize_t size = ftell(vff->file);
130	fseek(vff->file, pos, SEEK_SET);
131	return size;
132}