all repos — mgba @ f6755a6e1b7b0cf2b944cd8ca842746f11d6bf82

mGBA Game Boy Advance Emulator

src/platform/python/mgba/vfs.py (view raw)

  1# Copyright (c) 2013-2016 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# pylint: disable=invalid-name,unused-argument
  7from ._pylib import ffi, lib  # pylint: disable=no-name-in-module
  8import os
  9
 10
 11@ffi.def_extern()
 12def _vfpClose(vf):
 13    vfp = ffi.cast("struct VFilePy*", vf)
 14    ffi.from_handle(vfp.fileobj).close()
 15    return True
 16
 17
 18@ffi.def_extern()
 19def _vfpSeek(vf, offset, whence):
 20    vfp = ffi.cast("struct VFilePy*", vf)
 21    f = ffi.from_handle(vfp.fileobj)
 22    f.seek(offset, whence)
 23    return f.tell()
 24
 25
 26@ffi.def_extern()
 27def _vfpRead(vf, buffer, size):
 28    vfp = ffi.cast("struct VFilePy*", vf)
 29    pybuf = ffi.buffer(buffer, size)
 30    ffi.from_handle(vfp.fileobj).readinto(pybuf)
 31    return size
 32
 33
 34@ffi.def_extern()
 35def _vfpWrite(vf, buffer, size):
 36    vfp = ffi.cast("struct VFilePy*", vf)
 37    pybuf = ffi.buffer(buffer, size)
 38    ffi.from_handle(vfp.fileobj).write(pybuf)
 39    return size
 40
 41
 42@ffi.def_extern()
 43def _vfpMap(vf, size, flags):
 44    pass
 45
 46
 47@ffi.def_extern()
 48def _vfpUnmap(vf, memory, size):
 49    pass
 50
 51
 52@ffi.def_extern()
 53def _vfpTruncate(vf, size):
 54    vfp = ffi.cast("struct VFilePy*", vf)
 55    ffi.from_handle(vfp.fileobj).truncate(size)
 56
 57
 58@ffi.def_extern()
 59def _vfpSize(vf):
 60    vfp = ffi.cast("struct VFilePy*", vf)
 61    f = ffi.from_handle(vfp.fileobj)
 62    pos = f.tell()
 63    f.seek(0, os.SEEK_END)
 64    size = f.tell()
 65    f.seek(pos, os.SEEK_SET)
 66    return size
 67
 68
 69@ffi.def_extern()
 70def _vfpSync(vf, buffer, size):
 71    vfp = ffi.cast("struct VFilePy*", vf)
 72    f = ffi.from_handle(vfp.fileobj)
 73    if buffer and size:
 74        pos = f.tell()
 75        f.seek(0, os.SEEK_SET)
 76        _vfpWrite(vf, buffer, size)
 77        f.seek(pos, os.SEEK_SET)
 78    f.flush()
 79    os.fsync()
 80    return True
 81
 82
 83def open(f):  # pylint: disable=redefined-builtin
 84    handle = ffi.new_handle(f)
 85    vf = VFile(lib.VFileFromPython(handle), _no_gc=(f, handle))
 86    return vf
 87
 88
 89def open_path(path, mode="r"):
 90    flags = 0
 91    if mode.startswith("r"):
 92        flags |= os.O_RDONLY
 93    elif mode.startswith("w"):
 94        flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC
 95    elif mode.startswith("a"):
 96        flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND
 97    else:
 98        return None
 99
100    if "+" in mode[1:]:
101        flags |= os.O_RDWR
102    if "x" in mode[1:]:
103        flags |= os.O_EXCL
104
105    vf = lib.VFileOpen(path.encode("UTF-8"), flags)
106    if vf == ffi.NULL:
107        return None
108    return VFile(vf)
109
110
111class VFile:
112    def __init__(self, vf, _no_gc=None):
113        self.handle = vf
114        self._no_gc = _no_gc
115        self._claimed = False
116
117    def __del__(self):
118        if not self._claimed:
119            self.close()
120
121    def close(self):
122        if self._claimed:
123            return False
124        self._claimed = True
125        return bool(self.handle.close(self.handle))
126
127    def seek(self, offset, whence):
128        return self.handle.seek(self.handle, offset, whence)
129
130    def read(self, buffer, size):
131        return self.handle.read(self.handle, buffer, size)
132
133    def read_all(self, size=0):
134        if not size:
135            size = self.size()
136        buffer = ffi.new("char[%i]" % size)
137        size = self.handle.read(self.handle, buffer, size)
138        return ffi.unpack(buffer, size)
139
140    def readline(self, buffer, size):
141        return self.handle.readline(self.handle, buffer, size)
142
143    def write(self, buffer, size):
144        return self.handle.write(self.handle, buffer, size)
145
146    def map(self, size, flags):
147        return self.handle.map(self.handle, size, flags)
148
149    def unmap(self, memory, size):
150        self.handle.unmap(self.handle, memory, size)
151
152    def truncate(self, size):
153        self.handle.truncate(self.handle, size)
154
155    def size(self):
156        return self.handle.size(self.handle)
157
158    def sync(self, buffer, size):
159        return self.handle.sync(self.handle, buffer, size)