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