src/util/vfs/vfs-mem.c (view raw)
1/* Copyright (c) 2013-2015 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#include "util/vfs.h"
7#include "util/memory.h"
8
9struct VFileMem {
10 struct VFile d;
11 void* mem;
12 size_t size;
13 size_t offset;
14};
15
16static bool _vfmClose(struct VFile* vf);
17static bool _vfmCloseFree(struct VFile* vf);
18static off_t _vfmSeek(struct VFile* vf, off_t offset, int whence);
19static off_t _vfmSeekExpanding(struct VFile* vf, off_t offset, int whence);
20static ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size);
21static ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size);
22static ssize_t _vfmWriteExpanding(struct VFile* vf, const void* buffer, size_t size);
23static ssize_t _vfmWriteNoop(struct VFile* vf, const void* buffer, size_t size);
24static void* _vfmMap(struct VFile* vf, size_t size, int flags);
25static void _vfmUnmap(struct VFile* vf, void* memory, size_t size);
26static void _vfmTruncate(struct VFile* vf, size_t size);
27static void _vfmTruncateNoop(struct VFile* vf, size_t size);
28static ssize_t _vfmSize(struct VFile* vf);
29static bool _vfmSync(struct VFile* vf, const void* buffer, size_t size);
30
31struct VFile* VFileFromMemory(void* mem, size_t size) {
32 if (!mem || !size) {
33 return 0;
34 }
35
36 struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
37 if (!vfm) {
38 return 0;
39 }
40
41 vfm->mem = mem;
42 vfm->size = size;
43 vfm->offset = 0;
44 vfm->d.close = _vfmClose;
45 vfm->d.seek = _vfmSeek;
46 vfm->d.read = _vfmRead;
47 vfm->d.readline = VFileReadline;
48 vfm->d.write = _vfmWrite;
49 vfm->d.map = _vfmMap;
50 vfm->d.unmap = _vfmUnmap;
51 vfm->d.truncate = _vfmTruncateNoop;
52 vfm->d.size = _vfmSize;
53 vfm->d.sync = _vfmSync;
54
55 return &vfm->d;
56}
57
58struct VFile* VFileFromConstMemory(const void* mem, size_t size) {
59 if (!mem || !size) {
60 return 0;
61 }
62
63 struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
64 if (!vfm) {
65 return 0;
66 }
67
68 vfm->mem = (void*) mem;
69 vfm->size = size;
70 vfm->offset = 0;
71 vfm->d.close = _vfmClose;
72 vfm->d.seek = _vfmSeek;
73 vfm->d.read = _vfmRead;
74 vfm->d.readline = VFileReadline;
75 vfm->d.write = _vfmWriteNoop;
76 vfm->d.map = _vfmMap;
77 vfm->d.unmap = _vfmUnmap;
78 vfm->d.truncate = _vfmTruncateNoop;
79 vfm->d.size = _vfmSize;
80 vfm->d.sync = _vfmSync;
81
82 return &vfm->d;
83}
84
85struct VFile* VFileMemChunk(const void* mem, size_t size) {
86 struct VFileMem* vfm = malloc(sizeof(struct VFileMem));
87 if (!vfm) {
88 return 0;
89 }
90
91 vfm->size = size;
92 if (size) {
93 vfm->mem = anonymousMemoryMap(size);
94 if (mem) {
95 memcpy(vfm->mem, mem, size);
96 }
97 } else {
98 vfm->mem = 0;
99 }
100 vfm->offset = 0;
101 vfm->d.close = _vfmCloseFree;
102 vfm->d.seek = _vfmSeekExpanding;
103 vfm->d.read = _vfmRead;
104 vfm->d.readline = VFileReadline;
105 vfm->d.write = _vfmWriteExpanding;
106 vfm->d.map = _vfmMap;
107 vfm->d.unmap = _vfmUnmap;
108 vfm->d.truncate = _vfmTruncate;
109 vfm->d.size = _vfmSize;
110 vfm->d.sync = _vfmSync;
111
112 return &vfm->d;
113}
114
115void _vfmExpand(struct VFileMem* vfm, size_t newSize) {
116 void* oldBuf = vfm->mem;
117 vfm->mem = anonymousMemoryMap(newSize);
118 if (oldBuf) {
119 memcpy(vfm->mem, oldBuf, vfm->size);
120 mappedMemoryFree(oldBuf, vfm->size);
121 }
122 vfm->size = newSize;
123}
124
125bool _vfmClose(struct VFile* vf) {
126 struct VFileMem* vfm = (struct VFileMem*) vf;
127 vfm->mem = 0;
128 free(vfm);
129 return true;
130}
131
132bool _vfmCloseFree(struct VFile* vf) {
133 struct VFileMem* vfm = (struct VFileMem*) vf;
134 mappedMemoryFree(vfm->mem, vfm->size);
135 vfm->mem = 0;
136 free(vfm);
137 return true;
138}
139
140off_t _vfmSeek(struct VFile* vf, off_t offset, int whence) {
141 struct VFileMem* vfm = (struct VFileMem*) vf;
142
143 size_t position;
144 switch (whence) {
145 case SEEK_SET:
146 if (offset < 0) {
147 return -1;
148 }
149 position = offset;
150 break;
151 case SEEK_CUR:
152 if (offset < 0 && ((vfm->offset < (size_t) -offset) || (offset == INT_MIN))) {
153 return -1;
154 }
155 position = vfm->offset + offset;
156 break;
157 case SEEK_END:
158 if (offset < 0 && ((vfm->size < (size_t) -offset) || (offset == INT_MIN))) {
159 return -1;
160 }
161 position = vfm->size + offset;
162 break;
163 default:
164 return -1;
165 }
166
167 if (position > vfm->size) {
168 return -1;
169 }
170
171 vfm->offset = position;
172 return position;
173}
174
175off_t _vfmSeekExpanding(struct VFile* vf, off_t offset, int whence) {
176 struct VFileMem* vfm = (struct VFileMem*) vf;
177
178 size_t position;
179 switch (whence) {
180 case SEEK_SET:
181 if (offset < 0) {
182 return -1;
183 }
184 position = offset;
185 break;
186 case SEEK_CUR:
187 if (offset < 0 && ((vfm->offset < (size_t) -offset) || (offset == INT_MIN))) {
188 return -1;
189 }
190 position = vfm->offset + offset;
191 break;
192 case SEEK_END:
193 if (offset < 0 && ((vfm->size < (size_t) -offset) || (offset == INT_MIN))) {
194 return -1;
195 }
196 position = vfm->size + offset;
197 break;
198 default:
199 return -1;
200 }
201
202 if (position > vfm->size) {
203 _vfmExpand(vfm, position);
204 }
205
206 vfm->offset = position;
207 return position;
208}
209
210ssize_t _vfmRead(struct VFile* vf, void* buffer, size_t size) {
211 struct VFileMem* vfm = (struct VFileMem*) vf;
212
213 if (size + vfm->offset >= vfm->size) {
214 size = vfm->size - vfm->offset;
215 }
216
217 memcpy(buffer, (void*) ((uintptr_t) vfm->mem + vfm->offset), size);
218 vfm->offset += size;
219 return size;
220}
221
222ssize_t _vfmWrite(struct VFile* vf, const void* buffer, size_t size) {
223 struct VFileMem* vfm = (struct VFileMem*) vf;
224
225 if (size + vfm->offset >= vfm->size) {
226 size = vfm->size - vfm->offset;
227 }
228
229 memcpy((void*) ((uintptr_t) vfm->mem + vfm->offset), buffer, size);
230 vfm->offset += size;
231 return size;
232}
233
234ssize_t _vfmWriteExpanding(struct VFile* vf, const void* buffer, size_t size) {
235 struct VFileMem* vfm = (struct VFileMem*) vf;
236
237 if (size + vfm->offset >= vfm->size) {
238 _vfmExpand(vfm, vfm->offset + size);
239 }
240
241 memcpy((void*) ((uintptr_t) vfm->mem + vfm->offset), buffer, size);
242 vfm->offset += size;
243 return size;
244}
245
246
247ssize_t _vfmWriteNoop(struct VFile* vf, const void* buffer, size_t size) {
248 UNUSED(vf);
249 UNUSED(buffer);
250 UNUSED(size);
251 return -1;
252}
253
254void* _vfmMap(struct VFile* vf, size_t size, int flags) {
255 struct VFileMem* vfm = (struct VFileMem*) vf;
256
257 UNUSED(flags);
258 if (size > vfm->size) {
259 return 0;
260 }
261
262 return vfm->mem;
263}
264
265void _vfmUnmap(struct VFile* vf, void* memory, size_t size) {
266 UNUSED(vf);
267 UNUSED(memory);
268 UNUSED(size);
269}
270
271void _vfmTruncate(struct VFile* vf, size_t size) {
272 struct VFileMem* vfm = (struct VFileMem*) vf;
273 if (size > vfm->size) {
274 _vfmExpand(vfm, size);
275 } else {
276 // TODO
277 }
278}
279
280void _vfmTruncateNoop(struct VFile* vf, size_t size) {
281 // TODO: Return value?
282 UNUSED(vf);
283 UNUSED(size);
284}
285
286ssize_t _vfmSize(struct VFile* vf) {
287 struct VFileMem* vfm = (struct VFileMem*) vf;
288 return vfm->size;
289}
290
291bool _vfmSync(struct VFile* vf, const void* buffer, size_t size) {
292 UNUSED(vf);
293 UNUSED(buffer);
294 UNUSED(size);
295 return true;
296}