all repos — mgba @ 7020ea35a312967ff1e0cb0e4e7a4267149f0e29

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    @staticmethod
119    def fromEmpty():
120        return VFile(lib.VFileMemChunk(ffi.NULL, 0))
121
122    def __del__(self):
123        if not self._claimed:
124            self.close()
125
126    def close(self):
127        if self._claimed:
128            return False
129        self._claimed = True
130        return bool(self.handle.close(self.handle))
131
132    def seek(self, offset, whence):
133        return self.handle.seek(self.handle, offset, whence)
134
135    def read(self, buffer, size):
136        return self.handle.read(self.handle, buffer, size)
137
138    def read_all(self, size=0):
139        if not size:
140            size = self.size()
141        buffer = ffi.new("char[%i]" % size)
142        size = self.handle.read(self.handle, buffer, size)
143        return ffi.unpack(buffer, size)
144
145    def readline(self, buffer, size):
146        return self.handle.readline(self.handle, buffer, size)
147
148    def write(self, buffer, size):
149        return self.handle.write(self.handle, buffer, size)
150
151    def map(self, size, flags):
152        return self.handle.map(self.handle, size, flags)
153
154    def unmap(self, memory, size):
155        self.handle.unmap(self.handle, memory, size)
156
157    def truncate(self, size):
158        self.handle.truncate(self.handle, size)
159
160    def size(self):
161        return self.handle.size(self.handle)
162
163    def sync(self, buffer, size):
164        return self.handle.sync(self.handle, buffer, size)