all repos — mgba @ 8a3a2bf058973e01ab332bf58e1173927f4f38f8

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        res = _vfpWrite(vf, buffer, size)
 77        f.seek(pos, os.SEEK_SET)
 78        return res == size
 79    f.flush()
 80    os.fsync()
 81    return True
 82
 83
 84def open(f):  # pylint: disable=redefined-builtin
 85    handle = ffi.new_handle(f)
 86    vf = VFile(lib.VFileFromPython(handle), _no_gc=(f, handle))
 87    return vf
 88
 89
 90def open_path(path, mode="r"):
 91    flags = 0
 92    if mode.startswith("r"):
 93        flags |= os.O_RDONLY
 94    elif mode.startswith("w"):
 95        flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC
 96    elif mode.startswith("a"):
 97        flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND
 98    else:
 99        return None
100
101    if "+" in mode[1:]:
102        flags |= os.O_RDWR
103    if "x" in mode[1:]:
104        flags |= os.O_EXCL
105
106    vf = lib.VFileOpen(path.encode("UTF-8"), flags)
107    if vf == ffi.NULL:
108        return None
109    return VFile(vf)
110
111
112class VFile:
113    def __init__(self, vf, _no_gc=None):
114        self.handle = vf
115        self._no_gc = _no_gc
116        self._claimed = False
117
118    def __del__(self):
119        if not self._claimed:
120            self.close()
121
122    def close(self):
123        if self._claimed:
124            return False
125        self._claimed = True
126        return bool(self.handle.close(self.handle))
127
128    def seek(self, offset, whence):
129        return self.handle.seek(self.handle, offset, whence)
130
131    def read(self, buffer, size):
132        return self.handle.read(self.handle, buffer, size)
133
134    def read_all(self, size=0):
135        if not size:
136            size = self.size()
137        buffer = ffi.new("char[%i]" % size)
138        size = self.handle.read(self.handle, buffer, size)
139        return ffi.unpack(buffer, size)
140
141    def readline(self, buffer, size):
142        return self.handle.readline(self.handle, buffer, size)
143
144    def write(self, buffer, size):
145        return self.handle.write(self.handle, buffer, size)
146
147    def map(self, size, flags):
148        return self.handle.map(self.handle, size, flags)
149
150    def unmap(self, memory, size):
151        self.handle.unmap(self.handle, memory, size)
152
153    def truncate(self, size):
154        self.handle.truncate(self.handle, size)
155
156    def size(self):
157        return self.handle.size(self.handle)
158
159    def sync(self, buffer, size):
160        return self.handle.sync(self.handle, buffer, size)