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
qabstractfileengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "private/qabstractfileengine_p.h"
6#include "private/qfsfileengine_p.h"
7#ifdef QT_BUILD_CORE_LIB
8#include "private/qresource_p.h"
9#endif
10#include "qdatetime.h"
11#include "qreadwritelock.h"
12#include "qvariant.h"
13// built-in handlers
14#include "qdirlisting.h"
15#include "qstringbuilder.h"
16
17#include <QtCore/private/qfilesystementry_p.h>
18#include <QtCore/private/qfilesystemmetadata_p.h>
19#include <QtCore/private/qfilesystemengine_p.h>
20
22
23using namespace Qt::StringLiterals;
24
25static QString appendSlashIfNeeded(const QString &path)
26{
27 if (!path.isEmpty() && !path.endsWith(u'/')
28#ifdef Q_OS_ANDROID
29 && !path.startsWith("content:/"_L1)
30#endif
31 )
32 return QString{path + u'/'};
33 return path;
34}
35
36QAbstractFileEnginePrivate::~QAbstractFileEnginePrivate()
37 = default;
38
39/*!
40 \class QAbstractFileEngineHandler
41 \inmodule QtCore
42 \reentrant
43 \internal
44
45 \brief The QAbstractFileEngineHandler class provides a way to register
46 custom file engines with your application.
47
48 \ingroup io
49 \since 4.1
50
51 QAbstractFileEngineHandler is a factory for creating QAbstractFileEngine
52 objects (file engines), which are used internally by QFile, QFileInfo, and
53 QDir when working with files and directories.
54
55 When you open a file, Qt chooses a suitable file engine by passing the
56 file name from QFile or QDir through an internal list of registered file
57 engine handlers. The first handler to recognize the file name is used to
58 create the engine. Qt provides internal file engines for working with
59 regular files and resources, but you can also register your own
60 QAbstractFileEngine subclasses.
61
62 To install an application-specific file engine, you subclass
63 QAbstractFileEngineHandler and reimplement create(). When you instantiate
64 the handler (e.g. by creating an instance on the stack or on the heap), it
65 will automatically register with Qt. (The latest registered handler takes
66 precedence over existing handlers.)
67
68 For example:
69
70 \snippet code/src_corelib_io_qabstractfileengine.cpp 0
71
72 When the handler is destroyed, it is automatically removed from Qt.
73
74 The most common approach to registering a handler is to create an instance
75 as part of the start-up phase of your application. It is also possible to
76 limit the scope of the file engine handler to a particular area of
77 interest (e.g. a special file dialog that needs a custom file engine). By
78 creating the handler inside a local scope, you can precisely control the
79 area in which your engine will be applied without disturbing file
80 operations in other parts of your application.
81
82 \sa QAbstractFileEngine, QAbstractFileEngine::create()
83*/
84
85Q_CONSTINIT static QBasicAtomicInt qt_file_engine_handlers_in_use = Q_BASIC_ATOMIC_INITIALIZER(false);
86
87/*
88 All application-wide handlers are stored in this list. The mutex must be
89 acquired to ensure thread safety.
90 */
91Q_GLOBAL_STATIC(QReadWriteLock, fileEngineHandlerMutex, QReadWriteLock::Recursive)
92Q_CONSTINIT static bool qt_abstractfileenginehandlerlist_shutDown = false;
94{
96public:
98
100 {
101 QWriteLocker locker(fileEngineHandlerMutex());
102 qt_abstractfileenginehandlerlist_shutDown = true;
103 }
104};
105Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
106
107/*!
108 Constructs a file handler and registers it with Qt. Once created this
109 handler's create() function will be called (along with all the other
110 handlers) for any paths used. The most recently created handler that
111 recognizes the given path (i.e. that returns a QAbstractFileEngine) is
112 used for the new path.
113
114 \sa create()
115 */
116QAbstractFileEngineHandler::QAbstractFileEngineHandler()
117{
118 QWriteLocker locker(fileEngineHandlerMutex());
119 qt_file_engine_handlers_in_use.storeRelaxed(true);
120 fileEngineHandlers()->prepend(this);
121}
122
123/*!
124 Destroys the file handler. This will automatically unregister the handler
125 from Qt.
126 */
127QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
128{
129 QWriteLocker locker(fileEngineHandlerMutex());
130 // Remove this handler from the handler list only if the list is valid.
131 if (!qt_abstractfileenginehandlerlist_shutDown) {
132 QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
133 handlers->removeOne(this);
134 if (handlers->isEmpty())
135 qt_file_engine_handlers_in_use.storeRelaxed(false);
136 }
137}
138
139/*
140 \internal
141
142 Handles calls to custom file engine handlers.
143*/
144std::unique_ptr<QAbstractFileEngine> qt_custom_file_engine_handler_create(const QString &path)
145{
146 if (qt_file_engine_handlers_in_use.loadRelaxed()) {
147 QReadLocker locker(fileEngineHandlerMutex());
148
149 // check for registered handlers that can load the file
150 for (QAbstractFileEngineHandler *handler : std::as_const(*fileEngineHandlers())) {
151 if (auto engine = handler->create(path))
152 return engine;
153 }
154 }
155
156 return nullptr;
157}
158
159/*!
160 \fn std::unique_ptr<QAbstractFileEngine> QAbstractFileEngineHandler::create(const QString &fileName) const
161
162 If this file handler can handle \a fileName, this method creates a file
163 engine and returns it wrapped in a std::unique_ptr; otherwise returns
164 nullptr.
165
166 Example:
167
168 \snippet code/src_corelib_io_qabstractfileengine.cpp 1
169
170 \sa QAbstractFileEngine::create()
171*/
172
173/*!
174 Creates and returns a QAbstractFileEngine suitable for processing \a
175 fileName.
176
177 You should not need to call this function; use QFile, QFileInfo or
178 QDir directly instead.
179
180 If you reimplemnt this function, it should only return file
181 engines that knows how to handle \a fileName; otherwise, it should
182 return 0.
183
184 \sa QAbstractFileEngineHandler
185*/
186std::unique_ptr<QAbstractFileEngine> QAbstractFileEngine::create(const QString &fileName)
187{
188 QFileSystemEntry entry(fileName);
189 QFileSystemMetaData metaData;
190 auto engine = QFileSystemEngine::createLegacyEngine(entry, metaData);
191
192#ifndef QT_NO_FSFILEENGINE
193 if (!engine) // fall back to regular file engine
194 engine = std::make_unique<QFSFileEngine>(entry.filePath());
195#endif
196
197 return engine;
198}
199
200/*!
201 \class QAbstractFileEngine
202 \inmodule QtCore
203 \reentrant
204 \internal
205
206 \brief The QAbstractFileEngine class provides an abstraction for accessing
207 the filesystem.
208
209 \ingroup io
210 \since 4.1
211
212 The QDir, QFile, and QFileInfo classes all make use of a
213 QAbstractFileEngine internally. If you create your own QAbstractFileEngine
214 subclass (and register it with Qt by creating a QAbstractFileEngineHandler
215 subclass), your file engine will be used when the path is one that your
216 file engine handles.
217
218 A QAbstractFileEngine refers to one file or one directory. If the referent
219 is a file, the setFileName(), rename(), and remove() functions are
220 applicable. If the referent is a directory the mkdir(), rmdir(), and
221 beginEntryList() functions are applicable. In all cases the caseSensitive(),
222 isRelativePath(), fileFlags(), ownerId(), owner(), and fileTime()
223 functions are applicable.
224
225 A QAbstractFileEngine subclass can be created to do synchronous network I/O
226 based file system operations, local file system operations, or to operate
227 as a resource system to access file based resources.
228
229 \sa QAbstractFileEngineHandler
230*/
231
232/*!
233 \enum QAbstractFileEngine::FileName
234
235 These values are used to request a file name in a particular
236 format.
237
238 \value DefaultName The same filename that was passed to the
239 QAbstractFileEngine.
240 \value BaseName The name of the file excluding the path.
241 \value PathName The path to the file excluding the base name.
242 \value AbsoluteName The absolute path to the file (including
243 the base name).
244 \value AbsolutePathName The absolute path to the file (excluding
245 the base name).
246 \value AbsoluteLinkTarget The full file name of the file that this file is a
247 link to. (This will be empty if this file is not a link.)
248 \value RawLinkPath The raw link path of the file that this file is a
249 link to. (This will be empty if this file is not a link.)
250 \value CanonicalName Often very similar to AbsoluteLinkTarget. Will return the true path to the file.
251 \value CanonicalPathName Same as CanonicalName, excluding the base name.
252 \value BundleName Returns the name of the bundle implies BundleType is set.
253 \value JunctionName The full name of the directory that this NTFS junction
254 is linked to. (This will be empty if this file is not an NTFS junction.)
255
256 \omitvalue NFileNames
257
258 \sa fileName(), setFileName()
259*/
260
261/*!
262 \enum QAbstractFileEngine::FileFlag
263
264 The permissions and types of a file, suitable for OR'ing together.
265
266 \value ReadOwnerPerm The owner of the file has permission to read
267 it.
268 \value WriteOwnerPerm The owner of the file has permission to
269 write to it.
270 \value ExeOwnerPerm The owner of the file has permission to
271 execute it.
272 \value ReadUserPerm The current user has permission to read the
273 file.
274 \value WriteUserPerm The current user has permission to write to
275 the file.
276 \value ExeUserPerm The current user has permission to execute the
277 file.
278 \value ReadGroupPerm Members of the current user's group have
279 permission to read the file.
280 \value WriteGroupPerm Members of the current user's group have
281 permission to write to the file.
282 \value ExeGroupPerm Members of the current user's group have
283 permission to execute the file.
284 \value ReadOtherPerm All users have permission to read the file.
285 \value WriteOtherPerm All users have permission to write to the
286 file.
287 \value ExeOtherPerm All users have permission to execute the file.
288
289 \value LinkType The file is a link to another file (or link) in
290 the file system (i.e. not a file or directory).
291 \value FileType The file is a regular file to the file system
292 (i.e. not a link or directory)
293 \value BundleType \macos and iOS: the file is a bundle; implies DirectoryType
294 \value DirectoryType The file is a directory in the file system
295 (i.e. not a link or file).
296
297 \value HiddenFlag The file is hidden.
298 \value ExistsFlag The file actually exists in the file system.
299 \value RootFlag The file or the file pointed to is the root of the filesystem.
300 \value LocalDiskFlag The file resides on the local disk and can be passed to standard file functions.
301 \value Refresh Passing this flag will force the file engine to refresh all flags.
302
303 \omitvalue PermsMask
304 \omitvalue TypesMask
305 \omitvalue FlagsMask
306 \omitvalue FileInfoAll
307
308 \sa fileFlags(), setFileName()
309*/
310
311/*!
312 \enum QAbstractFileEngine::FileOwner
313
314 \value OwnerUser The user who owns the file.
315 \value OwnerGroup The group who owns the file.
316
317 \sa owner(), ownerId(), setFileName()
318*/
319
320/*!
321 Constructs a new QAbstractFileEngine that does not refer to any file or directory.
322
323 \sa setFileName()
324 */
325QAbstractFileEngine::QAbstractFileEngine() : d_ptr(new QAbstractFileEnginePrivate(this))
326{
327}
328
329/*!
330 \internal
331
332 Constructs a QAbstractFileEngine.
333 */
334QAbstractFileEngine::QAbstractFileEngine(QAbstractFileEnginePrivate &dd) : d_ptr(&dd)
335{
336 Q_ASSERT(d_ptr->q_ptr == this);
337}
338
339/*!
340 Destroys the QAbstractFileEngine.
341 */
342QAbstractFileEngine::~QAbstractFileEngine()
343{
344}
345
346/*!
347 \fn bool QAbstractFileEngine::open(QIODevice::OpenMode mode)
348
349 Opens the file in the specified \a mode. Returns \c true if the file
350 was successfully opened; otherwise returns \c false.
351
352 The \a mode is an OR combination of QIODevice::OpenMode and
353 QIODevice::HandlingMode values.
354
355 If the file is created as a result of this call, its permissions are
356 set according to \a permissision. Null value means an implementation-
357 specific default.
358*/
359bool QAbstractFileEngine::open(QIODevice::OpenMode openMode,
360 std::optional<QFile::Permissions> permissions)
361{
362 Q_UNUSED(openMode);
363 Q_UNUSED(permissions);
364 return false;
365}
366
367/*!
368 Closes the file, returning true if successful; otherwise returns \c false.
369
370 The default implementation always returns \c false.
371*/
372bool QAbstractFileEngine::close()
373{
374 return false;
375}
376
377/*!
378 \since 5.1
379
380 Flushes and syncs the file to disk.
381
382 Returns \c true if successful; otherwise returns \c false.
383 The default implementation always returns \c false.
384*/
385bool QAbstractFileEngine::syncToDisk()
386{
387 return false;
388}
389
390/*!
391 Flushes the open file, returning true if successful; otherwise returns
392 false.
393
394 The default implementation always returns \c false.
395*/
396bool QAbstractFileEngine::flush()
397{
398 return false;
399}
400
401/*!
402 Returns the size of the file.
403*/
404qint64 QAbstractFileEngine::size() const
405{
406 return 0;
407}
408
409/*!
410 Returns the current file position.
411
412 This is the position of the data read/write head of the file.
413*/
414qint64 QAbstractFileEngine::pos() const
415{
416 return 0;
417}
418
419/*!
420 \fn bool QAbstractFileEngine::seek(qint64 offset)
421
422 Sets the file position to the given \a offset. Returns \c true if
423 the position was successfully set; otherwise returns \c false.
424
425 The offset is from the beginning of the file, unless the
426 file is sequential.
427
428 \sa isSequential()
429*/
430bool QAbstractFileEngine::seek(qint64 pos)
431{
432 Q_UNUSED(pos);
433 return false;
434}
435
436/*!
437 Returns \c true if the file is a sequential access device; returns
438 false if the file is a direct access device.
439
440 Operations involving size() and seek(qint64) are not valid on
441 sequential devices.
442*/
443bool QAbstractFileEngine::isSequential() const
444{
445 return false;
446}
447
448/*!
449 Requests that the file is deleted from the file system. If the
450 operation succeeds return true; otherwise return false.
451
452 \sa setFileName(), rmdir()
453 */
454bool QAbstractFileEngine::remove()
455{
456 return false;
457}
458
459/*!
460 Copies the contents of this file to a file with the name \a newName.
461 Returns \c true on success; otherwise, false is returned.
462*/
463bool QAbstractFileEngine::copy(const QString &newName)
464{
465 Q_UNUSED(newName);
466 return false;
467}
468
469/*!
470 Requests that the file be renamed to \a newName in the file
471 system. If the operation succeeds return true; otherwise return
472 false.
473
474 \sa setFileName()
475 */
476bool QAbstractFileEngine::rename(const QString &newName)
477{
478 Q_UNUSED(newName);
479 return false;
480}
481
482/*!
483 \since 5.1
484
485 Requests that the file be renamed to \a newName in the file
486 system. If the new name already exists, it must be overwritten.
487 If the operation succeeds, returns \c true; otherwise returns
488 false.
489
490 \sa setFileName()
491 */
492bool QAbstractFileEngine::renameOverwrite(const QString &newName)
493{
494 Q_UNUSED(newName);
495 return false;
496}
497
498/*!
499 Creates a link from the file currently specified by fileName() to
500 \a newName. What a link is depends on the underlying filesystem
501 (be it a shortcut on Windows or a symbolic link on Unix). Returns
502 true if successful; otherwise returns \c false.
503*/
504bool QAbstractFileEngine::link(const QString &newName)
505{
506 Q_UNUSED(newName);
507 return false;
508}
509
510/*!
511 Requests that the directory \a dirName be created with the specified \a permissions.
512 If \a createParentDirectories is true, then any sub-directories in \a dirName
513 that don't exist must be created. If \a createParentDirectories is false then
514 any sub-directories in \a dirName must already exist for the function to
515 succeed. If the operation succeeds return true; otherwise return
516 false.
517
518 If \a permissions is null then implementation-specific default permissions are
519 used.
520
521 \sa setFileName(), rmdir(), isRelativePath()
522 */
523bool QAbstractFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
524 std::optional<QFile::Permissions> permissions) const
525{
526 Q_UNUSED(dirName);
527 Q_UNUSED(createParentDirectories);
528 Q_UNUSED(permissions);
529 return false;
530}
531
532/*!
533 Requests that the directory \a dirName is deleted from the file
534 system. When \a recurseParentDirectories is true, then any empty
535 parent-directories in \a dirName must also be deleted. If
536 \a recurseParentDirectories is false, only the \a dirName leaf-node
537 should be deleted. In most file systems a directory cannot be deleted
538 using this function if it is non-empty. If the operation succeeds
539 return true; otherwise return false.
540
541 \sa setFileName(), remove(), mkdir(), isRelativePath()
542 */
543bool QAbstractFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
544{
545 Q_UNUSED(dirName);
546 Q_UNUSED(recurseParentDirectories);
547 return false;
548}
549
550/*!
551 Requests that the file be set to size \a size. If \a size is larger
552 than the current file then it is filled with 0's, if smaller it is
553 simply truncated. If the operations succceeds return true; otherwise
554 return false;
555
556 \sa size()
557*/
558bool QAbstractFileEngine::setSize(qint64 size)
559{
560 Q_UNUSED(size);
561 return false;
562}
563
564/*!
565 Should return true if the underlying file system is case-sensitive;
566 otherwise return false.
567 */
568bool QAbstractFileEngine::caseSensitive() const
569{
570 return false;
571}
572
573/*!
574 Return true if the file referred to by this file engine has a
575 relative path; otherwise return false.
576
577 \sa setFileName()
578 */
579bool QAbstractFileEngine::isRelativePath() const
580{
581 return false;
582}
583
584/*!
585 This function should return the set of OR'd flags that are true
586 for the file engine's file, and that are in the \a type's OR'd
587 members.
588
589 In your reimplementation you can use the \a type argument as an
590 optimization hint and only return the OR'd set of members that are
591 true and that match those in \a type; in other words you can
592 ignore any members not mentioned in \a type, thus avoiding some
593 potentially expensive lookups or system calls.
594
595 \sa setFileName()
596*/
597QAbstractFileEngine::FileFlags QAbstractFileEngine::fileFlags(FileFlags type) const
598{
599 Q_UNUSED(type);
600 return {};
601}
602
603/*!
604 Requests that the file's permissions be set to \a perms. The argument
605 perms will be set to the OR-ed together combination of
606 QAbstractFileEngine::FileInfo, with only the QAbstractFileEngine::PermsMask being
607 honored. If the operations succceeds return true; otherwise return
608 false;
609
610 \sa size()
611*/
612bool QAbstractFileEngine::setPermissions(uint perms)
613{
614 Q_UNUSED(perms);
615 return false;
616}
617
618/*!
619 \since 5.9
620
621 Return an identifier that (hopefully) uniquely identifies this file in the
622 system. Returns an invalid QByteArray() if that cannot be calculated.
623*/
624QByteArray QAbstractFileEngine::id() const
625{
626 return QByteArray();
627}
628
629/*!
630 Return the file engine's current file name in the format
631 specified by \a file.
632
633 If you don't handle some \c FileName possibilities, return the
634 file name set in setFileName() when an unhandled format is
635 requested.
636
637 \sa setFileName(), FileName
638 */
639QString QAbstractFileEngine::fileName(FileName file) const
640{
641 Q_UNUSED(file);
642 return QString();
643}
644
645/*!
646 If \a owner is \c OwnerUser return the ID of the user who owns
647 the file. If \a owner is \c OwnerGroup return the ID of the group
648 that own the file. If you can't determine the owner return -2.
649
650 \sa owner(), setFileName(), FileOwner
651 */
652uint QAbstractFileEngine::ownerId(FileOwner owner) const
653{
654 Q_UNUSED(owner);
655 return 0;
656}
657
658/*!
659 If \a owner is \c OwnerUser return the name of the user who owns
660 the file. If \a owner is \c OwnerGroup return the name of the group
661 that own the file. If you can't determine the owner return
662 QString().
663
664 \sa ownerId(), setFileName(), FileOwner
665 */
666QString QAbstractFileEngine::owner(FileOwner owner) const
667{
668 Q_UNUSED(owner);
669 return QString();
670}
671
672
673/*!
674 \since 5.10
675
676 Sets the file \a time to \a newDate, returning true if successful;
677 otherwise returns false.
678
679 \sa fileTime()
680*/
681bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
682{
683 Q_UNUSED(newDate);
684 Q_UNUSED(time);
685 return false;
686}
687
688/*!
689 If \a time is \c BirthTime, return when the file was born (created). If \a
690 time is \c MetadataChangeTime, return when the file's metadata was last
691 changed. If \a time is \c ModificationTime, return when the file was most
692 recently modified. If \a time is \c AccessTime, return when the file was
693 most recently accessed (e.g. read or written). If the time cannot be
694 determined return QDateTime() (an invalid date time).
695
696 \sa setFileName(), QDateTime, QDateTime::isValid(), FileTime
697 */
698QDateTime QAbstractFileEngine::fileTime(QFile::FileTime time) const
699{
700 Q_UNUSED(time);
701 return QDateTime();
702}
703
704/*!
705 Sets the file engine's file name to \a file. This file name is the
706 file that the rest of the virtual functions will operate on.
707
708 \sa rename()
709 */
710void QAbstractFileEngine::setFileName(const QString &file)
711{
712 Q_UNUSED(file);
713}
714
715/*!
716 Returns the native file handle for this file engine. This handle must be
717 used with care; its value and type are platform specific, and using it
718 will most likely lead to non-portable code.
719*/
720int QAbstractFileEngine::handle() const
721{
722 return -1;
723}
724
725/*!
726 \since 4.3
727
728 Returns \c true if the current position is at the end of the file; otherwise,
729 returns \c false.
730
731 This function bases its behavior on calling extension() with
732 AtEndExtension. If the engine does not support this extension, false is
733 returned.
734
735 \sa extension(), supportsExtension(), QFile::atEnd()
736*/
737bool QAbstractFileEngine::atEnd() const
738{
739 return const_cast<QAbstractFileEngine *>(this)->extension(AtEndExtension);
740}
741
742/*!
743 \since 4.4
744
745 Maps \a size bytes of the file into memory starting at \a offset.
746 Returns a pointer to the memory if successful; otherwise returns \c false
747 if, for example, an error occurs.
748
749 This function bases its behavior on calling extension() with
750 MapExtensionOption. If the engine does not support this extension, 0 is
751 returned.
752
753 \a flags is currently not used, but could be used in the future.
754
755 \sa unmap(), supportsExtension()
756 */
757
758uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
759{
760 const MapExtensionOption option(offset, size, flags);
761 MapExtensionReturn r;
762 if (!extension(MapExtension, &option, &r))
763 return nullptr;
764 return r.address;
765}
766
767/*!
768 \since 4.4
769
770 Unmaps the memory \a address. Returns \c true if the unmap succeeds; otherwise
771 returns \c false.
772
773 This function bases its behavior on calling extension() with
774 UnMapExtensionOption. If the engine does not support this extension, false is
775 returned.
776
777 \sa map(), supportsExtension()
778 */
779bool QAbstractFileEngine::unmap(uchar *address)
780{
781 const UnMapExtensionOption options(address);
782 return extension(UnMapExtension, &options);
783}
784
785/*!
786 \since 5.10
787
788 Duplicates the contents of this file (starting from the current position)
789 to the file specified by the engine \a target.
790
791 Returns \c true on success; otherwise, \c false is returned.
792 */
793QAbstractFileEngine::TriStateResult QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
794{
795 Q_UNUSED(target);
796 return TriStateResult::NotSupported;
797}
798
799/*!
800 \since 4.3
801 \class QAbstractFileEngineIterator
802 \inmodule QtCore
803 \brief The QAbstractFileEngineIterator class provides an iterator
804 interface for custom file engines.
805 \internal
806
807 If all you want is to iterate over entries in a directory, see
808 QDirListing instead. This class is useful only for custom file engine
809 authors.
810
811 QAbstractFileEngineIterator is a unidirectional single-use virtual
812 iterator that plugs into QDirListing, providing transparent proxy
813 iteration for custom file engines (for example, QResourceFileEngine).
814
815 You can subclass QAbstractFileEngineIterator to provide an iterator when
816 writing your own file engine. To plug the iterator into your file system,
817 you simply return an instance of this subclass from a reimplementation of
818 QAbstractFileEngine::beginEntryList().
819
820 Example:
821
822 \snippet code/src_corelib_io_qabstractfileengine.cpp 2
823
824 QAbstractFileEngineIterator is associated with a path, name filters, and
825 entry filters. The path is the directory that the iterator lists entries
826 in. The name filters and entry filters are provided for file engines that
827 can optimize directory listing at the iterator level (e.g., network file
828 systems that need to minimize network traffic), but they can also be
829 ignored by the iterator subclass; QAbstractFileEngineIterator already
830 provides the required filtering logics in the matchesFilters() function.
831 You can call dirName() to get the directory name, nameFilters() to get a
832 stringlist of name filters, and filters() to get the entry filters.
833
834 The pure virtual function advance(), as its name implies, advances the
835 iterator to the next entry in the current directory; if the operation
836 was successful this method returns \c true, otherwise it returns \c
837 false. You have to reimplement this function in your sub-class to work
838 with your file engine implementation.
839
840 The pure virtual function currentFileName() returns the name of the
841 current entry without advancing the iterator. The currentFilePath()
842 function is provided for convenience; it returns the full path of the
843 current entry.
844
845 Here is an example of how to implement an iterator that returns each of
846 three fixed entries in sequence.
847
848 \snippet code/src_corelib_io_qabstractfileengine.cpp 3
849
850 Note: QAbstractFileEngineIterator does not deal with QDir::IteratorFlags;
851 it simply returns entries for a single directory.
852
853 \sa QDirListing
854*/
855
856/*!
857 \typedef QAbstractFileEngine::Iterator
858 \since 4.3
859
860 Synonym for QAbstractFileEngineIterator.
861*/
862
863/*!
864 \typedef QAbstractFileEngine::IteratorUniquePtr
865 \since 6.8
866
867 Synonym for std::unique_ptr<Iterator> (that is a
868 std::unique_ptr<QAbstractFileEngineIterator>).
869*/
870
871/*!
872 Constructs a QAbstractFileEngineIterator, using the entry filters \a
873 filters, and wildcard name filters \a nameFilters.
874*/
875QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path, QDir::Filters filters,
876 const QStringList &nameFilters)
877 : m_filters(filters),
878 m_nameFilters(nameFilters),
879 m_path(appendSlashIfNeeded(path))
880{
881}
882
883QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path,
884 QDirListing::IteratorFlags filters,
885 const QStringList &nameFilters)
886 : m_listingFilters(filters),
887 m_nameFilters(nameFilters),
888 m_path(appendSlashIfNeeded(path))
889{
890}
891
892/*!
893 Destroys the QAbstractFileEngineIterator.
894
895 \sa QDirListing
896*/
897QAbstractFileEngineIterator::~QAbstractFileEngineIterator()
898{
899}
900
901/*!
902
903 Returns the path for this iterator. The path is set by beginEntryList().
904 The path should't be changed once iteration begins.
905
906 \sa nameFilters(), filters()
907*/
908QString QAbstractFileEngineIterator::path() const
909{
910 return m_path;
911}
912
913/*!
914 Returns the name filters for this iterator.
915
916 \sa QDir::nameFilters(), filters(), path()
917*/
918QStringList QAbstractFileEngineIterator::nameFilters() const
919{
920 return m_nameFilters;
921}
922
923/*!
924 Returns the entry filters for this iterator.
925
926 \sa QDir::filter(), nameFilters(), path()
927*/
928QDir::Filters QAbstractFileEngineIterator::filters() const
929{
930 return m_filters;
931}
932
933/*!
934 \fn QString QAbstractFileEngineIterator::currentFileName() const = 0
935
936 This pure virtual function returns the name of the current directory
937 entry, excluding the path.
938
939 \sa currentFilePath()
940*/
941
942/*!
943 Returns the path to the current directory entry. It's the same as
944 prepending path() to the return value of currentFileName().
945
946 \sa currentFileName()
947*/
948QString QAbstractFileEngineIterator::currentFilePath() const
949{
950 QString name = currentFileName();
951 if (name.isNull())
952 return name;
953
954 return path() + name;
955}
956
957/*!
958 The virtual function returns a QFileInfo for the current directory
959 entry. This function is provided for convenience. It can also be slightly
960 faster than creating a QFileInfo object yourself, as the object returned
961 by this function might contain cached information that QFileInfo otherwise
962 would have to access through the file engine.
963
964 \sa currentFileName()
965*/
966QFileInfo QAbstractFileEngineIterator::currentFileInfo() const
967{
968 QString path = currentFilePath();
969 if (m_fileInfo.filePath() != path)
970 m_fileInfo.setFile(path);
971
972 // return a shallow copy
973 return m_fileInfo;
974}
975
976/*!
977 \fn virtual bool QAbstractFileEngineIterator::advance() = 0
978
979 This pure virtual function advances the iterator to the next directory
980 entry; if the operation was successful this method returns \c true,
981 otherwise it returs \c false.
982
983 This function can optionally make use of nameFilters() and filters() to
984 optimize its performance.
985
986 Reimplement this function in a subclass to advance the iterator.
987*/
988
989/*!
990 Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used
991 to iterate over the entries in \a path, using \a filters for entry
992 filtering and \a filterNames for name filtering. This function is called
993 by QDirListing to initiate directory iteration.
994
995 \sa QDirListing
996*/
997QAbstractFileEngine::IteratorUniquePtr
998QAbstractFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
999 const QStringList &filterNames)
1000{
1001 Q_UNUSED(path);
1002 Q_UNUSED(filters);
1003 Q_UNUSED(filterNames);
1004 return {};
1005}
1006
1007/*!
1008 Reads a number of characters from the file into \a data. At most
1009 \a maxlen characters will be read.
1010
1011 Returns -1 if a fatal error occurs, or 0 if there are no bytes to
1012 read.
1013*/
1014qint64 QAbstractFileEngine::read(char *data, qint64 maxlen)
1015{
1016 Q_UNUSED(data);
1017 Q_UNUSED(maxlen);
1018 return -1;
1019}
1020
1021/*!
1022 Writes \a len bytes from \a data to the file. Returns the number
1023 of characters written on success; otherwise returns -1.
1024*/
1025qint64 QAbstractFileEngine::write(const char *data, qint64 len)
1026{
1027 Q_UNUSED(data);
1028 Q_UNUSED(len);
1029 return -1;
1030}
1031
1032/*!
1033 This function reads one line, terminated by a '\\n' character, from the
1034 file info \a data. At most \a maxlen characters will be read. The
1035 end-of-line character is included.
1036*/
1037qint64 QAbstractFileEngine::readLine(char *data, qint64 maxlen)
1038{
1039 qint64 readSoFar = 0;
1040 while (readSoFar < maxlen) {
1041 char c;
1042 qint64 readResult = read(&c, 1);
1043 if (readResult <= 0)
1044 return (readSoFar > 0) ? readSoFar : -1;
1045 ++readSoFar;
1046 *data++ = c;
1047 if (c == '\n')
1048 return readSoFar;
1049 }
1050 return readSoFar;
1051}
1052
1053/*!
1054 \enum QAbstractFileEngine::Extension
1055 \since 4.3
1056
1057 This enum describes the types of extensions that the file engine can
1058 support. Before using these extensions, you must verify that the extension
1059 is supported (i.e., call supportsExtension()).
1060
1061 \value AtEndExtension Whether the current file position is at the end of
1062 the file or not. This extension allows file engines that implement local
1063 buffering to report end-of-file status without having to check the size of
1064 the file. It is also useful for sequential files, where the size of the
1065 file cannot be used to determine whether or not you have reached the end.
1066 This extension returns \c true if the file is at the end; otherwise it returns
1067 false. The input and output arguments to extension() are ignored.
1068
1069 \value FastReadLineExtension Whether the file engine provides a
1070 fast implementation for readLine() or not. If readLine() remains
1071 unimplemented in the file engine, QAbstractFileEngine will provide
1072 an implementation based on calling read() repeatedly. If
1073 supportsExtension() returns \c false for this extension, however,
1074 QIODevice can provide a faster implementation by making use of its
1075 internal buffer. For engines that already provide a fast readLine()
1076 implementation, returning false for this extension can avoid
1077 unnecessary double-buffering in QIODevice.
1078
1079 \value MapExtension Whether the file engine provides the ability to map
1080 a file to memory.
1081
1082 \value UnMapExtension Whether the file engine provides the ability to
1083 unmap memory that was previously mapped.
1084*/
1085
1086/*!
1087 \class QAbstractFileEngine::ExtensionOption
1088 \inmodule QtCore
1089 \since 4.3
1090 \brief provides an extended input argument to QAbstractFileEngine's
1091 extension support.
1092
1093 \sa QAbstractFileEngine::extension()
1094*/
1095
1096/*!
1097 \class QAbstractFileEngine::ExtensionReturn
1098 \inmodule QtCore
1099 \since 4.3
1100 \brief provides an extended output argument to QAbstractFileEngine's
1101 extension support.
1102
1103 \sa QAbstractFileEngine::extension()
1104*/
1105
1106/*!
1107 \since 4.3
1108
1109 This virtual function can be reimplemented in a QAbstractFileEngine
1110 subclass to provide support for extensions. The \a option argument is
1111 provided as input to the extension, and this function can store output
1112 results in \a output.
1113
1114 The behavior of this function is determined by \a extension; see the
1115 Extension documentation for details.
1116
1117 You can call supportsExtension() to check if an extension is supported by
1118 the file engine.
1119
1120 By default, no extensions are supported, and this function returns \c false.
1121
1122 \sa supportsExtension(), Extension
1123*/
1124bool QAbstractFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
1125{
1126 Q_UNUSED(extension);
1127 Q_UNUSED(option);
1128 Q_UNUSED(output);
1129 return false;
1130}
1131
1132/*!
1133 \since 4.3
1134
1135 This virtual function returns \c true if the file engine supports \a
1136 extension; otherwise, false is returned. By default, no extensions are
1137 supported.
1138
1139 \sa extension()
1140*/
1141bool QAbstractFileEngine::supportsExtension(Extension extension) const
1142{
1143 Q_UNUSED(extension);
1144 return false;
1145}
1146
1147/*!
1148 Returns the QFile::FileError that resulted from the last failed
1149 operation. If QFile::UnspecifiedError is returned, QFile will
1150 use its own idea of the error status.
1151
1152 \sa QFile::FileError, errorString()
1153 */
1154QFile::FileError QAbstractFileEngine::error() const
1155{
1156 Q_D(const QAbstractFileEngine);
1157 return d->fileError;
1158}
1159
1160/*!
1161 Returns the human-readable message appropriate to the current error
1162 reported by error(). If no suitable string is available, an
1163 empty string is returned.
1164
1165 \sa error()
1166 */
1167QString QAbstractFileEngine::errorString() const
1168{
1169 Q_D(const QAbstractFileEngine);
1170 return d->errorString;
1171}
1172
1173/*!
1174 Sets the error type to \a error, and the error string to \a errorString.
1175 Call this function to set the error values returned by the higher-level
1176 classes.
1177
1178 \sa QFile::error(), QIODevice::errorString(), QIODevice::setErrorString()
1179*/
1180void QAbstractFileEngine::setError(QFile::FileError error, const QString &errorString)
1181{
1182 Q_D(QAbstractFileEngine);
1183 d->fileError = error;
1184 d->errorString = errorString;
1185}
1186
1187QT_END_NAMESPACE
static QString appendSlashIfNeeded(const QString &path)