Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwasmlocalfileengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 Qt Group
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4#include <QtCore/QDebug>
5#include <QtCore/QUrl>
6
8
9using namespace Qt::StringLiterals;
10
11// Custom URL scheme for files handled by this file engine. A complete file URL can
12// look like
13//
14// "weblocalfile:/n/file.ext"
15//
16// where n is a counter to ensure uniqueness, needed since web platform gives us the file name only
17// and does not provide the file path.
18//
19// The scheme may be visible to end users if the application displays it, so
20// we avoid using "wasm" and instead say "web", which should be more recognizable.
21static constexpr QLatin1StringView wasmlocalfileScheme = "weblocalfile"_L1;
22
23// Instantiate the engine, the system will pick it up automatically
24// Never destroy it to avoid problems with static destruction.
25// The OS will reclaim the memory anyway,
26// TODO: cleanup on QApplication destruction and re-init on QApplication re-creation.
28
29QWasmFileEngineHandler::QWasmFileEngineHandler()
30{
31}
32
36
38{
39 if (!QWasmFileEngineHandler::isWasmFileName(fileName))
40 return {};
41
42 // Check if it's a File or FileSystemFileHandle
43 if (singleton->m_files.contains(fileName)) {
44 qstdweb::File file = singleton->m_files.value(fileName);
45 return std::make_unique<QWasmFileEngine>(fileName, file);
46 } else if (singleton->m_fileSystemFiles.contains(fileName)) {
47 qstdweb::FileSystemFileHandle file = singleton->m_fileSystemFiles.value(fileName);
48 return std::make_unique<QWasmFileEngine>(fileName, file);
49 }
50
51 // Not an error, this function will be called with partial paths like "weblocalfile:/1/"
52 return {};
53}
54
55// Check if this is a wasm filename by checking the URL scheme.
56bool QWasmFileEngineHandler::isWasmFileName(const QString& fileName)
57{
58 return QUrl(fileName).scheme() == wasmlocalfileScheme;
59}
60
61// Creates a wasm filename using the custom URL scheme and a counter.
62QString QWasmFileEngineHandler::makeWasmFileName(const QString &nativeFileName)
63{
64 static std::atomic<uint64_t> sid = 0;
65 const uint64_t id = ++sid;
66 return wasmlocalfileScheme + QStringLiteral(":/%1/%2").arg(id).arg(nativeFileName);
67}
68
69// Extracts the native filename from the custom URL (removes scheme and counter).
70QString QWasmFileEngineHandler::nativeFileName(const QString &wasmFileName)
71{
72 QUrl url(wasmFileName);
73 if (url.scheme() == wasmlocalfileScheme) {
74 QString path = url.path();
75 // Path is "/n/filename", find the second '/' and extract the filename
76 const qsizetype idx = path.indexOf(u'/', 1);
77 if (idx != -1)
78 return path.mid(idx + 1);
79 }
80 return wasmFileName;
81}
82
83// Adds a File to the set of open files. Returns a prefixed wasm file name.
84QString QWasmFileEngineHandler::addFile(qstdweb::File file)
85{
86 QString nativeFileName = QString::fromStdString(file.name());
87 QString wasmFileName = makeWasmFileName(nativeFileName);
88 singleton->m_files.insert(wasmFileName, file);
89 return wasmFileName;
90}
91
92// Adds a FileSystemFileHandle to the set of open files. Returns a prefixed wasm file name.
93QString QWasmFileEngineHandler::addFile(qstdweb::FileSystemFileHandle file)
94{
95 QString nativeFileName = QString::fromStdString(file.name());
96 QString wasmFileName = makeWasmFileName(nativeFileName);
97 singleton->m_fileSystemFiles.insert(wasmFileName, file);
98 return wasmFileName;
99}
100
101// Removes a File or FileSystemFileHandle from the set of open file handlers
102void QWasmFileEngineHandler::removeFile(const QString fileName)
103{
104 singleton->m_files.remove(fileName);
105 singleton->m_fileSystemFiles.remove(fileName);
106}
107
109{
110 return singleton->m_files.value(fileName);
111}
112
114{
115 return singleton->m_fileSystemFiles.value(fileName);
116}
117
118/*!
119 \class QWasmFileEngine
120 \brief The QWasmFileEngine class provides a QAbstractFileEngine
121 for files that has the prefix ':weblocalfile/'.
122*/
123
124// Constructs a QWasmFileEngine with a File for read-only access
125QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::File file)
128{
129 // TODO use m_blobDevice in unbuffered mode? if there is already a buffer higher up.
130}
131
132// Constructs a QWasmFileEngine with a FileSystemFileHandle for read-write access
133QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::FileSystemFileHandle file)
136{
137
138}
139
144
145bool QWasmFileEngine::open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions)
146{
147 Q_UNUSED(permissions);
148 m_openMode = openMode;
149
150 if (m_fileDevice)
151 return m_fileDevice->open(openMode);
152 else if (m_blobDevice)
153 return m_blobDevice->open(openMode);
154
155 return false;
156}
157
159{
160 if (m_openMode == QIODevice::NotOpen)
161 return false;
162
163 bool success = true;
164 if (m_fileDevice) {
165 m_fileDevice->close();
166 }
167 if (m_blobDevice) {
168 m_blobDevice->close();
169 }
170
171 m_openMode = QIODevice::NotOpen;
172 return success;
173}
174
176{
177 return true;
178}
179
181{
182 return true;
183}
184
186{
187 if (m_fileDevice)
188 return m_fileDevice->size();
189 if (m_blobDevice)
190 return m_blobDevice->size();
191 return 0;
192}
193
195{
196 if (m_fileDevice)
197 return m_fileDevice->pos();
198 if (m_blobDevice)
199 return m_blobDevice->pos();
200 return 0;
201}
202
203bool QWasmFileEngine::seek(qint64 pos)
204{
205 if (m_fileDevice)
206 return m_fileDevice->seek(pos);
207 if (m_blobDevice)
208 return m_blobDevice->seek(pos);
209 return false;
210}
211
213{
214 return false;
215}
216
218{
219 return false;
220}
221
222bool QWasmFileEngine::copy(const QString &newName)
223{
224 Q_UNUSED(newName);
225 return false;
226}
227
228bool QWasmFileEngine::rename(const QString &newName)
229{
230 Q_UNUSED(newName);
231 return false;
232}
233
234bool QWasmFileEngine::renameOverwrite(const QString &newName)
235{
236 Q_UNUSED(newName);
237 return false;
238}
239
240bool QWasmFileEngine::link(const QString &newName)
241{
242 Q_UNUSED(newName);
243 return false;
244}
245
246bool QWasmFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
247 std::optional<QFile::Permissions> permissions) const
248{
249 Q_UNUSED(dirName);
250 Q_UNUSED(createParentDirectories);
251 Q_UNUSED(permissions);
252 return false;
253}
254
255bool QWasmFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
256{
257 Q_UNUSED(dirName);
258 Q_UNUSED(recurseParentDirectories);
259 return false;
260}
261
262bool QWasmFileEngine::setSize(qint64 size)
263{
264 Q_UNUSED(size);
265 return false;
266}
267
269{
270 return true;
271}
272
274{
275 return false;
276}
277
278
280{
281 return type & (QAbstractFileEngine::FileFlag::ExistsFlag |
282 QAbstractFileEngine::FileFlag::FileType |
283 QAbstractFileEngine::FileFlag::ReadOwnerPerm |
284 QAbstractFileEngine::FileFlag::WriteOwnerPerm);
285}
286
288{
289 Q_UNUSED(perms);
290 return false;
291}
292
294{
295 return {};
296}
297
298QString QWasmFileEngine::fileName(FileName file) const
299{
300 switch (file) {
301 case DefaultName:
302 case AbsoluteName:
303 case CanonicalName:
304 return m_fileName;
305 case BaseName: {
306 QString native = QWasmFileEngineHandler::nativeFileName(m_fileName);
307 QFileInfo info(native);
308 return info.fileName();
309 }
310 case PathName:
311 case AbsolutePathName:
312 case CanonicalPathName: {
313 QString native = QWasmFileEngineHandler::nativeFileName(m_fileName);
314 QFileInfo info(native);
315 QString path = info.path();
316 return path.isEmpty() ? "."_L1 : path;
317 }
318 default:
319 return QString();
320 }
321}
322
324{
325 return 0;
326}
327
329{
330 return {};
331}
332
333bool QWasmFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
334{
335 Q_UNUSED(newDate);
336 Q_UNUSED(time);
337 return false;
338}
339
340QDateTime QWasmFileEngine::fileTime(QFile::FileTime time) const
341{
342 Q_UNUSED(time);
343 return {};
344}
345
346void QWasmFileEngine::setFileName(const QString &file)
347{
348 if (m_fileName == file)
349 return;
350 close();
351 m_fileName = file;
352}
353
355{
356 return -1;
357}
358
360{
361 Q_UNUSED(target);
362 return QAbstractFileEngine::TriStateResult::NotSupported;
363}
364
365QAbstractFileEngine::IteratorUniquePtr QWasmFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
366 const QStringList &filterNames)
367{
368 Q_UNUSED(path);
369 Q_UNUSED(filters);
370 Q_UNUSED(filterNames);
371 return nullptr;
372}
373
374qint64 QWasmFileEngine::read(char *data, qint64 maxlen)
375{
376 if (!(m_openMode & QIODevice::ReadOnly))
377 return -1;
378
379 if (m_fileDevice)
380 return m_fileDevice->read(data, maxlen);
381 if (m_blobDevice)
382 return m_blobDevice->read(data, maxlen);
383 return -1;
384}
385
386qint64 QWasmFileEngine::readLine(char *data, qint64 maxlen)
387{
388 if (!(m_openMode & QIODevice::ReadOnly))
389 return -1;
390
391 if (m_fileDevice)
392 return m_fileDevice->readLine(data, maxlen);
393 if (m_blobDevice)
394 return m_blobDevice->readLine(data, maxlen);
395 return -1;
396}
397
398qint64 QWasmFileEngine::write(const char *data, qint64 len)
399{
400 if (!(m_openMode & QIODevice::WriteOnly))
401 return -1;
402
403 if (m_fileDevice)
404 return m_fileDevice->write(data, len);
405 return -1;
406}
407
408bool QWasmFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
409{
410 Q_UNUSED(extension);
411 Q_UNUSED(option);
412 Q_UNUSED(output);
413 return false;
414}
415
416bool QWasmFileEngine::supportsExtension(Extension extension) const
417{
418 Q_UNUSED(extension);
419 return false;
420}
421
422QT_END_NAMESPACE
qstdweb::FileSystemFileHandle getFileSystemFile(const QString fileName)
virtual ~QWasmFileEngineHandler() override
virtual std::unique_ptr< QAbstractFileEngine > create(const QString &fileName) const override
If this file handler can handle fileName, this method creates a file engine and returns it wrapped in...
qstdweb::File getFile(const QString fileName)
The QWasmFileEngine class provides a QAbstractFileEngine for files that has the prefix ':weblocalfile...
virtual bool link(const QString &newName) override
Creates a link from the file currently specified by fileName() to newName.
virtual bool flush() override
Flushes the open file, returning true if successful; otherwise returns false.
virtual qint64 read(char *data, qint64 maxlen) override
Reads a number of characters from the file into data.
virtual void setFileName(const QString &file) override
Sets the file engine's file name to file.
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const override
Requests that the directory dirName is deleted from the file system.
virtual bool setSize(qint64 size) override
Requests that the file be set to size size.
virtual bool copy(const QString &newName) override
Copies the contents of this file to a file with the name newName.
virtual uint ownerId(FileOwner) const override
If owner is OwnerUser return the ID of the user who owns the file.
virtual bool caseSensitive() const override
Should return true if the underlying file system is case-sensitive; otherwise return false.
virtual QString fileName(FileName file=DefaultName) const override
Return the file engine's current file name in the format specified by file.
virtual qint64 pos() const override
Returns the current file position.
virtual bool supportsExtension(Extension extension) const override
virtual bool extension(Extension extension, const ExtensionOption *option=nullptr, ExtensionReturn *output=nullptr) override
virtual bool close() override
Closes the file, returning true if successful; otherwise returns false.
virtual bool isSequential() const override
Returns true if the file is a sequential access device; returns false if the file is a direct access ...
virtual bool syncToDisk() override
virtual bool seek(qint64 pos) override
Sets the file position to the given offset.
virtual qint64 write(const char *data, qint64 len) override
Writes len bytes from data to the file.
virtual TriStateResult cloneTo(QAbstractFileEngine *target) override
virtual bool rename(const QString &newName) override
Requests that the file be renamed to newName in the file system.
virtual QByteArray id() const override
virtual QString owner(FileOwner) const override
If owner is OwnerUser return the name of the user who owns the file.
virtual qint64 readLine(char *data, qint64 maxlen) override
This function reads one line, terminated by a '\n' character, from the file info data.
virtual bool setPermissions(uint perms) override
Requests that the file's permissions be set to perms.
virtual int handle() const override
Returns the native file handle for this file engine.
virtual bool remove() override
Requests that the file is deleted from the file system.
virtual IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) override
Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used to iterate over the entries in pat...
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const override
This function should return the set of OR'd flags that are true for the file engine's file,...
virtual bool mkdir(const QString &dirName, bool createParentDirectories, std::optional< QFile::Permissions > permissions=std::nullopt) const override
Requests that the directory dirName be created with the specified permissions.
virtual qint64 size() const override
Returns the size of the file.
QWasmFileEngine(const QString &fileName, qstdweb::File file)
virtual bool renameOverwrite(const QString &newName) override
virtual bool isRelativePath() const override
Return true if the file referred to by this file engine has a relative path; otherwise return false.
virtual QDateTime fileTime(QFile::FileTime time) const override
If time is BirthTime, return when the file was born (created).
virtual bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override
Combined button and popup list for selecting options.
static constexpr QLatin1StringView wasmlocalfileScheme