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
116 def __del__(self):
117 self.close()
118
119 def close(self):
120 return bool(self.handle.close(self.handle))
121
122 def seek(self, offset, whence):
123 return self.handle.seek(self.handle, offset, whence)
124
125 def read(self, buffer, size):
126 return self.handle.read(self.handle, buffer, size)
127
128 def read_all(self, size=0):
129 if not size:
130 size = self.size()
131 buffer = ffi.new("char[%i]" % size)
132 size = self.handle.read(self.handle, buffer, size)
133 return ffi.unpack(buffer, size)
134
135 def readline(self, buffer, size):
136 return self.handle.readline(self.handle, buffer, size)
137
138 def write(self, buffer, size):
139 return self.handle.write(self.handle, buffer, size)
140
141 def map(self, size, flags):
142 return self.handle.map(self.handle, size, flags)
143
144 def unmap(self, memory, size):
145 self.handle.unmap(self.handle, memory, size)
146
147 def truncate(self, size):
148 self.handle.truncate(self.handle, size)
149
150 def size(self):
151 return self.handle.size(self.handle)
152
153 def sync(self, buffer, size):
154 return self.handle.sync(self.handle, buffer, size)