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#ifndef QIODEVICE_P_H
5#define QIODEVICE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of QIODevice. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "QtCore/qbytearray.h"
19#include "QtCore/qiodevice.h"
20#include "QtCore/qobjectdefs.h"
21#include "QtCore/qstring.h"
22#include "QtCore/qvarlengtharray.h"
23#include "private/qringbuffer_p.h"
24#ifndef QT_NO_QOBJECT
25#include "private/qobject_p.h"
26#else
27static constexpr int QObjectPrivateVersion = QT_VERSION;
28#endif
29
30QT_BEGIN_NAMESPACE
31
32#ifndef QIODEVICE_BUFFERSIZE
33#define QIODEVICE_BUFFERSIZE 16384
34#endif
35
36Q_CORE_EXPORT int qt_subtract_from_timeout(int timeout, int elapsed);
37
38class Q_CORE_EXPORT QIODevicePrivate
39#ifndef QT_NO_QOBJECT
40 : public QObjectPrivate
41#endif
42{
43 Q_DECLARE_PUBLIC(QIODevice)
44 Q_DISABLE_COPY_MOVE(QIODevicePrivate)
45
46public:
47 QIODevicePrivate(decltype(QObjectPrivateVersion) version = QObjectPrivateVersion);
48 virtual ~QIODevicePrivate();
49
50 enum class ReadLineOption {
51 NotNullTerminated,
52 NullTerminated,
53 };
54 Q_DECLARE_FLAGS(ReadLineOptions, ReadLineOption)
55
56 // The size of this class is a subject of the library hook data.
57 // When adding a new member, do not make gaps and be aware
58 // about the padding. Accordingly, adjust offsets in
59 // tests/auto/other/toolsupport and bump the TypeInformationVersion
60 // field in src/corelib/global/qhooks.cpp, to notify the developers.
61 qint64 pos = 0;
62 qint64 devicePos = 0;
63 qint64 transactionPos = 0;
64
65 class QRingBufferRef
66 {
67 QRingBuffer *m_buf;
68 inline QRingBufferRef() : m_buf(nullptr) { }
69 friend class QIODevicePrivate;
70 public:
71 // wrap functions from QRingBuffer
72 inline void setChunkSize(int size) { Q_ASSERT(m_buf); m_buf->setChunkSize(size); }
73 inline int chunkSize() const { Q_ASSERT(m_buf); return m_buf->chunkSize(); }
74 inline qint64 nextDataBlockSize() const { return (m_buf ? m_buf->nextDataBlockSize() : Q_INT64_C(0)); }
75 inline const char *readPointer() const { return (m_buf ? m_buf->readPointer() : nullptr); }
76 inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const { Q_ASSERT(m_buf); return m_buf->readPointerAtPosition(pos, length); }
77 inline void free(qint64 bytes) { Q_ASSERT(m_buf); m_buf->free(bytes); }
78 inline char *reserve(qint64 bytes) { Q_ASSERT(m_buf); return m_buf->reserve(bytes); }
79 inline char *reserveFront(qint64 bytes) { Q_ASSERT(m_buf); return m_buf->reserveFront(bytes); }
80 inline void truncate(qint64 pos) { Q_ASSERT(m_buf); m_buf->truncate(pos); }
81 inline void chop(qint64 bytes) { Q_ASSERT(m_buf); m_buf->chop(bytes); }
82 inline bool isEmpty() const { return !m_buf || m_buf->isEmpty(); }
83 inline int getChar() { return (m_buf ? m_buf->getChar() : -1); }
84 inline void putChar(char c) { Q_ASSERT(m_buf); m_buf->putChar(c); }
85 inline void ungetChar(char c) { Q_ASSERT(m_buf); m_buf->ungetChar(c); }
86 inline qint64 size() const { return (m_buf ? m_buf->size() : Q_INT64_C(0)); }
87 inline void clear() { if (m_buf) m_buf->clear(); }
88 inline qint64 indexOf(char c) const { return (m_buf ? m_buf->indexOf(c, maxLength: m_buf->size()) : Q_INT64_C(-1)); }
89 inline qint64 indexOf(char c, qint64 maxLength, qint64 pos = 0) const { return (m_buf ? m_buf->indexOf(c, maxLength, pos) : Q_INT64_C(-1)); }
90 inline qint64 read(char *data, qint64 maxLength) { return (m_buf ? m_buf->read(data, maxLength) : Q_INT64_C(0)); }
91 inline QByteArray read() { return (m_buf ? m_buf->read() : QByteArray()); }
92 inline qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const { return (m_buf ? m_buf->peek(data, maxLength, pos) : Q_INT64_C(0)); }
93 inline void append(const char *data, qint64 size) { Q_ASSERT(m_buf); m_buf->append(data, size); }
94 inline void append(const QByteArray &qba) { Q_ASSERT(m_buf); m_buf->append(qba); }
95 inline qint64 skip(qint64 length) { return (m_buf ? m_buf->skip(length) : Q_INT64_C(0)); }
96 qint64 readLine(char *data, qint64 maxLength,
97 ReadLineOptions option = ReadLineOption::NullTerminated)
98 {
99 const auto appendNullByte = option & ReadLineOption::NullTerminated;
100 return !m_buf ? Q_INT64_C(-1) :
101 appendNullByte ? m_buf->readLine(data, maxLength) :
102 m_buf->readLineWithoutTerminatingNull(data, maxLength);
103 }
104 inline bool canReadLine() const { return m_buf && m_buf->canReadLine(); }
105 };
106
107 QRingBufferRef buffer;
108 QRingBufferRef writeBuffer;
109 const QByteArray *currentWriteChunk = nullptr;
110 int readChannelCount = 0;
111 int writeChannelCount = 0;
112 int currentReadChannel = 0;
113 int currentWriteChannel = 0;
114 int readBufferChunkSize = QIODEVICE_BUFFERSIZE;
115 int writeBufferChunkSize = 0;
116
117 QVarLengthArray<QRingBuffer, 2> readBuffers;
118 QVarLengthArray<QRingBuffer, 1> writeBuffers;
119 QString errorString;
120 QIODevice::OpenMode openMode = QIODevice::NotOpen;
121
122 bool transactionStarted = false;
123 bool baseReadLineDataCalled = false;
124
125 virtual bool putCharHelper(char c);
126
127 enum AccessMode : quint8 {
128 Unset,
129 Sequential,
130 RandomAccess
131 };
132 mutable AccessMode accessMode = Unset;
133 inline bool isSequential() const
134 {
135 if (accessMode == Unset)
136 accessMode = q_func()->isSequential() ? Sequential : RandomAccess;
137 return accessMode == Sequential;
138 }
139
140 inline bool isBufferEmpty() const
141 {
142 return buffer.isEmpty() || (transactionStarted && isSequential()
143 && transactionPos == buffer.size());
144 }
145 bool allWriteBuffersEmpty() const;
146
147 void seekBuffer(qint64 newPos);
148
149 inline void setCurrentReadChannel(int channel)
150 {
151 buffer.m_buf = (channel < readBuffers.size() ? &readBuffers[channel] : nullptr);
152 currentReadChannel = channel;
153 }
154 inline void setCurrentWriteChannel(int channel)
155 {
156 writeBuffer.m_buf = (channel < writeBuffers.size() ? &writeBuffers[channel] : nullptr);
157 currentWriteChannel = channel;
158 }
159 void setReadChannelCount(int count);
160 void setWriteChannelCount(int count);
161
162 qint64 read(char *data, qint64 maxSize, bool peeking = false);
163 qint64 readLine(char *data, qint64 maxSize,
164 ReadLineOption option = ReadLineOption::NullTerminated);
165
166 virtual qint64 peek(char *data, qint64 maxSize);
167 virtual QByteArray peek(qint64 maxSize);
168 qint64 skipByReading(qint64 maxSize);
169 qint64 skipLine();
170 void write(const char *data, qint64 size);
171
172 inline bool isWriteChunkCached(const char *data, qint64 size) const
173 {
174 return currentWriteChunk != nullptr
175 && currentWriteChunk->constData() == data
176 && currentWriteChunk->size() == size;
177 }
178
179#ifdef QT_NO_QOBJECT
180 QIODevice *q_ptr = nullptr;
181#endif
182};
183
184Q_DECLARE_OPERATORS_FOR_FLAGS(QIODevicePrivate::ReadLineOptions)
185
186QT_END_NAMESPACE
187
188#endif // QIODEVICE_P_H
189

source code of qtbase/src/corelib/io/qiodevice_p.h