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