Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfiledevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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 "qplatformdefs.h"
5#include "qfiledevice.h"
6#include "qfiledevice_p.h"
7#include "qfsfileengine_p.h"
8
9#ifdef QT_NO_QOBJECT
10#define tr(X) QString::fromLatin1(X)
11#endif
12
14
15#ifndef QFILE_WRITEBUFFER_SIZE
16#define QFILE_WRITEBUFFER_SIZE 16384
17#endif
18
25
27
29{
30 if (!fileEngine)
31 fileEngine = std::make_unique<QFSFileEngine>();
32 return fileEngine.get();
33}
34
40
42{
43 error = err;
44 errorString = errStr;
45}
46
48{
49 error = err;
51}
52
133//************* QFileDevice
134
200#ifdef QT_NO_QOBJECT
203{
204}
206 : QIODevice(dd)
207{
208}
209#else
221 : QIODevice(*new QFileDevicePrivate, parent)
222{
223}
228 : QIODevice(dd, parent)
229{
230}
231#endif
232
240
250{
251 Q_D(const QFileDevice);
252 return d->fileEngine && d->fileEngine->isSequential();
253}
254
268{
269 Q_D(const QFileDevice);
270 if (!isOpen() || !d->fileEngine)
271 return -1;
272
273 return d->fileEngine->handle();
274}
275
281{
282 return QString();
283}
284
290{
291 Q_D(QFileDevice);
292 if (!d->fileEngine) {
293 qWarning("QFileDevice::flush: No file engine. Is IODevice open?");
294 return false;
295 }
296
297 if (!d->writeBuffer.isEmpty()) {
298 qint64 size = d->writeBuffer.nextDataBlockSize();
299 qint64 written = d->fileEngine->write(d->writeBuffer.readPointer(), size);
300 if (written > 0)
301 d->writeBuffer.free(written);
302 if (written != size) {
303 QFileDevice::FileError err = d->fileEngine->error();
306 d->setError(err, d->fileEngine->errorString());
307 return false;
308 }
309 }
310
311 if (!d->fileEngine->flush()) {
312 QFileDevice::FileError err = d->fileEngine->error();
315 d->setError(err, d->fileEngine->errorString());
316 return false;
317 }
318 return true;
319}
320
327{
328 Q_D(QFileDevice);
329 if (!isOpen())
330 return;
331 bool flushed = flush();
333
334 // reset write buffer
335 d->lastWasWrite = false;
336 d->writeBuffer.clear();
337
338 // reset cached size
339 d->cachedSize = 0;
340
341 // keep earlier error from flush
342 if (d->fileEngine->close() && flushed)
343 unsetError();
344 else if (flushed)
345 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
346}
347
352{
353 return QIODevice::pos();
354}
355
366{
367 Q_D(const QFileDevice);
368
369 // If there's buffered data left, we're not at the end.
370 if (!d->isBufferEmpty())
371 return false;
372
373 if (!isOpen())
374 return true;
375
376 if (!d->ensureFlushed())
377 return false;
378
379 // If the file engine knows best, say what it says.
380 if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
381 // Check if the file engine supports AtEndExtension, and if it does,
382 // check if the file engine claims to be at the end.
383 return d->fileEngine->atEnd();
384 }
385
386 // if it looks like we are at the end, or if size is not cached,
387 // fall through to bytesAvailable() to make sure.
388 if (pos() < d->cachedSize)
389 return false;
390
391 // Fall back to checking how much is available (will stat files).
392 return bytesAvailable() == 0;
393}
394
411{
412 Q_D(QFileDevice);
413 if (!isOpen()) {
414 qWarning("QFileDevice::seek: IODevice is not open");
415 return false;
416 }
417
418 if (!d->ensureFlushed())
419 return false;
420
421 if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
422 QFileDevice::FileError err = d->fileEngine->error();
425 d->setError(err, d->fileEngine->errorString());
426 return false;
427 }
428 unsetError();
429 return true;
430}
431
436{
437 Q_D(QFileDevice);
438 if (!d->ensureFlushed())
439 return -1;
440
441 qint64 read;
442 if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
443 read = d->fileEngine->readLine(data, maxlen);
444 } else {
445 // Fall back to QIODevice's readLine implementation if the engine
446 // cannot do it faster.
448 }
449
450 if (read < maxlen) {
451 // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
452 d->cachedSize = 0;
453 }
454
455 return read;
456}
457
462{
463 Q_D(QFileDevice);
464 if (!len)
465 return 0;
466 unsetError();
467 if (!d->ensureFlushed())
468 return -1;
469
470 const qint64 read = d->fileEngine->read(data, len);
471 if (read < 0) {
472 QFileDevice::FileError err = d->fileEngine->error();
475 d->setError(err, d->fileEngine->errorString());
476 }
477
478 if (read < len) {
479 // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
480 d->cachedSize = 0;
481 }
482
483 return read;
484}
485
490{
491#ifdef QT_NO_QOBJECT
493#else
494
495 // Cutoff for code that doesn't only touch the buffer.
496 qint64 writeBufferSize = writeBuffer.size();
497 if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= writeBufferChunkSize
498#ifdef Q_OS_WIN
499 || ((openMode & QIODevice::Text) && c == '\n'
500 && writeBufferSize + 2 >= writeBufferChunkSize)
501#endif
502 ) {
504 }
505
508 qWarning("QIODevice::putChar: Closed device");
509 else
510 qWarning("QIODevice::putChar: ReadOnly device");
511 return false;
512 }
513
514 // Make sure the device is positioned correctly.
515 const bool sequential = isSequential();
516 if (pos != devicePos && !sequential && !q_func()->seek(pos))
517 return false;
518
519 lastWasWrite = true;
520
521 int len = 1;
522#ifdef Q_OS_WIN
523 if ((openMode & QIODevice::Text) && c == '\n') {
524 ++len;
525 *writeBuffer.reserve(1) = '\r';
526 }
527#endif
528
529 // Write to buffer.
530 *writeBuffer.reserve(1) = c;
531
532 if (!sequential) {
533 pos += len;
534 devicePos += len;
535 if (!buffer.isEmpty())
536 buffer.skip(len);
537 }
538
539 return true;
540#endif
541}
542
547{
548 Q_D(QFileDevice);
549 unsetError();
550 d->lastWasWrite = true;
551 bool buffered = !(d->openMode & Unbuffered);
552
553 // Flush buffered data if this read will overflow.
554 if (buffered && (d->writeBuffer.size() + len) > d->writeBufferChunkSize) {
555 if (!flush())
556 return -1;
557 }
558
559 // Write directly to the engine if the block size is larger than
560 // the write buffer size.
561 if (!buffered || len > d->writeBufferChunkSize) {
562 const qint64 ret = d->fileEngine->write(data, len);
563 if (ret < 0) {
564 QFileDevice::FileError err = d->fileEngine->error();
567 d->setError(err, d->fileEngine->errorString());
568 }
569 return ret;
570 }
571
572 // Write to the buffer.
573 d->writeBuffer.append(data, len);
574 return len;
575}
576
587{
588 Q_D(const QFileDevice);
589 return d->error;
590}
591
598{
599 Q_D(QFileDevice);
600 d->setError(QFileDevice::NoError);
601}
602
611{
612 Q_D(const QFileDevice);
613 if (!d->ensureFlushed())
614 return 0;
615 d->cachedSize = d->engine()->size();
616 return d->cachedSize;
617}
618
630{
631 Q_D(QFileDevice);
632 if (!d->ensureFlushed())
633 return false;
634 d->engine();
635 if (isOpen() && d->fileEngine->pos() > sz)
636 seek(sz);
637 if (d->fileEngine->setSize(sz)) {
638 unsetError();
639 d->cachedSize = sz;
640 return true;
641 }
642 d->cachedSize = 0;
643 d->setError(QFile::ResizeError, d->fileEngine->errorString());
644 return false;
645}
646
653QFile::Permissions QFileDevice::permissions() const
654{
655 Q_D(const QFileDevice);
656 QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
657 return QFile::Permissions::fromInt(perms.toInt()); //ewww
658}
659
670bool QFileDevice::setPermissions(Permissions permissions)
671{
672 Q_D(QFileDevice);
673 if (d->engine()->setPermissions(permissions.toInt())) {
674 unsetError();
675 return true;
676 }
677 d->setError(QFile::PermissionsError, d->fileEngine->errorString());
678 return false;
679}
680
715{
716 Q_D(QFileDevice);
717 if (d->engine()
718 && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
719 unsetError();
720 uchar *address = d->fileEngine->map(offset, size, flags);
721 if (address == nullptr)
722 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
723 return address;
724 }
725 return nullptr;
726}
727
736{
737 Q_D(QFileDevice);
738 if (d->engine()
739 && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
740 unsetError();
741 bool success = d->fileEngine->unmap(address);
742 if (!success)
743 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
744 return success;
745 }
746 d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
747 return false;
748}
749
775{
776 Q_D(const QFileDevice);
777
778 if (d->engine())
779 return d->engine()->fileTime(time);
780
781 return QDateTime();
782}
783
794{
795 Q_D(QFileDevice);
796
797 if (!d->engine()) {
798 d->setError(QFileDevice::UnspecifiedError, tr("No file engine available"));
799 return false;
800 }
801
802 if (!d->fileEngine->setFileTime(newDate, fileTime)) {
803 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
804 return false;
805 }
806
807 unsetError();
808 return true;
809}
810
812
813#ifndef QT_NO_QOBJECT
814#include "moc_qfiledevice.cpp"
815#endif
\inmodule QtCore \reentrant
\inmodule QtCore\reentrant
Definition qdatetime.h:283
bool putCharHelper(char c) override
std::unique_ptr< QAbstractFileEngine > fileEngine
virtual QAbstractFileEngine * engine() const
void setError(QFileDevice::FileError err)
QFileDevice::FileError error
\inmodule QtCore
Definition qfiledevice.h:32
qint64 readLineData(char *data, qint64 maxlen) override
\reimp
qint64 readData(char *data, qint64 maxlen) override
\reimp
bool flush()
Flushes any buffered data to the file.
~QFileDevice()
Destroys the file device, closing it if necessary.
QDateTime fileTime(QFileDevice::FileTime time) const
qint64 pos() const override
\reimp
bool seek(qint64 offset) override
For random-access devices, this function sets the current position to pos, returning true on success,...
qint64 size() const override
Returns the size of the file.
void unsetError()
Sets the file's error to QFileDevice::NoError.
virtual bool resize(qint64 sz)
Sets the file size (in bytes) sz.
qint64 writeData(const char *data, qint64 len) override
\reimp
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
int handle() const
Returns the file handle of the file.
QFileDevice()
\macro QT_USE_NODISCARD_FILE_OPEN \macro QT_NO_USE_NODISCARD_FILE_OPEN
bool setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime)
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
FileError error() const
Returns the file error status.
bool isSequential() const override
Returns true if the file can only be manipulated sequentially; otherwise returns false.
virtual QString fileName() const
Returns the name of the file.
FileError
This enum describes the errors that may be returned by the error() function.
Definition qfiledevice.h:39
virtual bool setPermissions(Permissions permissionSpec)
Sets the permissions for the file to the permissions specified.
bool unmap(uchar *address)
Unmaps the memory address.
void close() override
Calls QFileDevice::flush() and closes the file.
virtual Permissions permissions() const
Returns the complete OR-ed together combination of QFile::Permission for the file.
\inmodule QtCore
Definition qfile.h:93
QIODevice::OpenMode openMode
bool isSequential() const
virtual bool putCharHelper(char c)
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
virtual qint64 readLineData(char *data, qint64 maxlen)
Reads up to maxSize characters into data and returns the number of characters read.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtCore
Definition qobject.h:103
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
#define QFILE_WRITEBUFFER_SIZE
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define qWarning
Definition qlogging.h:166
return ret
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLbitfield flags
GLenum GLuint GLintptr offset
const GLubyte * c
GLuint writeBuffer
GLuint GLuint64EXT address
GLenum GLsizei len
@ NoError
Definition main.cpp:34
#define tr(X)
unsigned char uchar
Definition qtypes.h:32
long long qint64
Definition qtypes.h:60
QObject::connect nullptr