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)