Deinline QRingBuffer class
Reduce the size of .text section in QtCore by 4.5KB and in QtNetwork by 26.5KB. Change-Id: If7998776166b9681c1e4b24c51d40444aa996d7a Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
f81dda39dd
commit
e227b8ecf6
@ -13,7 +13,7 @@ OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
|
||||
|
||||
#qt code
|
||||
QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
|
||||
qdebug.o qmalloc.o qglobal.o \
|
||||
qringbuffer.o qdebug.o qmalloc.o qglobal.o \
|
||||
qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
|
||||
qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o qvector.o \
|
||||
qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \
|
||||
@ -44,6 +44,7 @@ DEPEND_SRC = \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
|
||||
$(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
|
||||
@ -242,6 +243,9 @@ qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
|
||||
qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
|
||||
|
||||
qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
|
||||
|
||||
qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
|
||||
|
||||
|
@ -88,6 +88,7 @@ QTOBJS= \
|
||||
qglobal.obj \
|
||||
qhash.obj \
|
||||
qiodevice.obj \
|
||||
qringbuffer.obj \
|
||||
qdebug.obj \
|
||||
qlist.obj \
|
||||
qlinkedlist.obj \
|
||||
|
327
src/corelib/tools/qringbuffer.cpp
Normal file
327
src/corelib/tools/qringbuffer.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Copyright (C) 2015 Alex Trotsenko <alex1973tr@gmail.com>
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL21$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** As a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "private/qringbuffer_p.h"
|
||||
#include <string.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Access the bytes at a specified position the out-variable length will
|
||||
contain the amount of bytes readable from there, e.g. the amount still
|
||||
the same QByteArray
|
||||
*/
|
||||
const char *QRingBuffer::readPointerAtPosition(qint64 pos, qint64 &length) const
|
||||
{
|
||||
if (pos >= 0) {
|
||||
pos += head;
|
||||
for (int i = 0; i < buffers.size(); ++i) {
|
||||
length = (i == tailBuffer ? tail : buffers[i].size());
|
||||
if (length > pos) {
|
||||
length -= pos;
|
||||
return buffers[i].constData() + pos;
|
||||
}
|
||||
pos -= length;
|
||||
}
|
||||
}
|
||||
|
||||
length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QRingBuffer::free(qint64 bytes)
|
||||
{
|
||||
while (bytes > 0) {
|
||||
const qint64 blockSize = buffers.first().size() - head;
|
||||
|
||||
if (tailBuffer == 0 || blockSize > bytes) {
|
||||
// keep a single block around if it does not exceed
|
||||
// the basic block size, to avoid repeated allocations
|
||||
// between uses of the buffer
|
||||
if (bufferSize <= bytes) {
|
||||
if (buffers.first().size() <= basicBlockSize) {
|
||||
bufferSize = 0;
|
||||
head = tail = 0;
|
||||
} else {
|
||||
clear(); // try to minify/squeeze us
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
head += int(bytes);
|
||||
bufferSize -= bytes;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bufferSize -= blockSize;
|
||||
bytes -= blockSize;
|
||||
buffers.removeFirst();
|
||||
--tailBuffer;
|
||||
head = 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *QRingBuffer::reserve(qint64 bytes)
|
||||
{
|
||||
if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
|
||||
return 0;
|
||||
|
||||
const qint64 newSize = bytes + tail;
|
||||
// if need buffer reallocation
|
||||
if (newSize > buffers.last().size()) {
|
||||
if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
|
||||
|| quint64(newSize) >= QByteArray::MaxSize)) {
|
||||
// shrink this buffer to its current size
|
||||
buffers.last().resize(tail);
|
||||
|
||||
// create a new QByteArray
|
||||
buffers.append(QByteArray());
|
||||
++tailBuffer;
|
||||
tail = 0;
|
||||
}
|
||||
buffers.last().resize(qMax(basicBlockSize, tail + int(bytes)));
|
||||
}
|
||||
|
||||
char *writePtr = buffers.last().data() + tail;
|
||||
bufferSize += bytes;
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
tail += int(bytes);
|
||||
return writePtr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Allocate data at buffer head
|
||||
*/
|
||||
char *QRingBuffer::reserveFront(qint64 bytes)
|
||||
{
|
||||
if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
|
||||
return 0;
|
||||
|
||||
if (head < bytes) {
|
||||
buffers.first().remove(0, head);
|
||||
if (tailBuffer == 0)
|
||||
tail -= head;
|
||||
|
||||
buffers.prepend(QByteArray());
|
||||
head = qMax(basicBlockSize, int(bytes));
|
||||
buffers.first().resize(head);
|
||||
++tailBuffer;
|
||||
}
|
||||
|
||||
head -= int(bytes);
|
||||
bufferSize += bytes;
|
||||
return buffers.first().data() + head;
|
||||
}
|
||||
|
||||
void QRingBuffer::chop(qint64 bytes)
|
||||
{
|
||||
while (bytes > 0) {
|
||||
if (tailBuffer == 0 || tail > bytes) {
|
||||
// keep a single block around if it does not exceed
|
||||
// the basic block size, to avoid repeated allocations
|
||||
// between uses of the buffer
|
||||
if (bufferSize <= bytes) {
|
||||
if (buffers.first().size() <= basicBlockSize) {
|
||||
bufferSize = 0;
|
||||
head = tail = 0;
|
||||
} else {
|
||||
clear(); // try to minify/squeeze us
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
tail -= int(bytes);
|
||||
bufferSize -= bytes;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bufferSize -= tail;
|
||||
bytes -= tail;
|
||||
buffers.removeLast();
|
||||
--tailBuffer;
|
||||
tail = buffers.last().size();
|
||||
}
|
||||
}
|
||||
|
||||
void QRingBuffer::clear()
|
||||
{
|
||||
buffers.erase(buffers.begin() + 1, buffers.end());
|
||||
buffers.first().clear();
|
||||
|
||||
head = tail = 0;
|
||||
tailBuffer = 0;
|
||||
bufferSize = 0;
|
||||
}
|
||||
|
||||
qint64 QRingBuffer::indexOf(char c) const
|
||||
{
|
||||
qint64 index = 0;
|
||||
qint64 j = head;
|
||||
for (int i = 0; i < buffers.size(); ++i) {
|
||||
const char *ptr = buffers[i].constData() + j;
|
||||
j = index + (i == tailBuffer ? tail : buffers[i].size()) - j;
|
||||
|
||||
while (index < j) {
|
||||
if (*ptr++ == c)
|
||||
return index;
|
||||
++index;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64 QRingBuffer::indexOf(char c, qint64 maxLength) const
|
||||
{
|
||||
qint64 index = 0;
|
||||
qint64 j = head;
|
||||
for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
|
||||
const char *ptr = buffers[i].constData() + j;
|
||||
j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
|
||||
|
||||
while (index < j) {
|
||||
if (*ptr++ == c)
|
||||
return index;
|
||||
++index;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64 QRingBuffer::read(char *data, qint64 maxLength)
|
||||
{
|
||||
const qint64 bytesToRead = qMin(size(), maxLength);
|
||||
qint64 readSoFar = 0;
|
||||
while (readSoFar < bytesToRead) {
|
||||
const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
|
||||
nextDataBlockSize());
|
||||
if (data)
|
||||
memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
|
||||
readSoFar += bytesToReadFromThisBlock;
|
||||
free(bytesToReadFromThisBlock);
|
||||
}
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Read an unspecified amount (will read the first buffer)
|
||||
*/
|
||||
QByteArray QRingBuffer::read()
|
||||
{
|
||||
if (bufferSize == 0)
|
||||
return QByteArray();
|
||||
|
||||
QByteArray qba(buffers.takeFirst());
|
||||
|
||||
qba.reserve(0); // avoid that resizing needlessly reallocates
|
||||
if (tailBuffer == 0) {
|
||||
qba.resize(tail);
|
||||
tail = 0;
|
||||
buffers.append(QByteArray());
|
||||
} else {
|
||||
--tailBuffer;
|
||||
}
|
||||
qba.remove(0, head); // does nothing if head is 0
|
||||
head = 0;
|
||||
bufferSize -= qba.size();
|
||||
return qba;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Peek the bytes from a specified position
|
||||
*/
|
||||
qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const
|
||||
{
|
||||
qint64 readSoFar = 0;
|
||||
|
||||
if (pos >= 0) {
|
||||
pos += head;
|
||||
for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) {
|
||||
qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size());
|
||||
|
||||
if (pos < blockLength) {
|
||||
blockLength = qMin(blockLength - pos, maxLength - readSoFar);
|
||||
memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength);
|
||||
readSoFar += blockLength;
|
||||
pos = 0;
|
||||
} else {
|
||||
pos -= blockLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Append a new buffer to the end
|
||||
*/
|
||||
void QRingBuffer::append(const QByteArray &qba)
|
||||
{
|
||||
if (tail == 0) {
|
||||
buffers.last() = qba;
|
||||
} else {
|
||||
buffers.last().resize(tail);
|
||||
buffers.append(qba);
|
||||
++tailBuffer;
|
||||
}
|
||||
tail = qba.size();
|
||||
bufferSize += tail;
|
||||
}
|
||||
|
||||
qint64 QRingBuffer::readLine(char *data, qint64 maxLength)
|
||||
{
|
||||
if (!data || --maxLength <= 0)
|
||||
return -1;
|
||||
|
||||
qint64 i = indexOf('\n', maxLength);
|
||||
i = read(data, i >= 0 ? (i + 1) : maxLength);
|
||||
|
||||
// Terminate it.
|
||||
data[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -66,117 +66,17 @@ public:
|
||||
return bufferSize == 0 ? Q_NULLPTR : (buffers.first().constData() + head);
|
||||
}
|
||||
|
||||
// access the bytes at a specified position
|
||||
// the out-variable length will contain the amount of bytes readable
|
||||
// from there, e.g. the amount still the same QByteArray
|
||||
inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
|
||||
if (pos >= 0) {
|
||||
pos += head;
|
||||
for (int i = 0; i < buffers.size(); ++i) {
|
||||
length = (i == tailBuffer ? tail : buffers[i].size());
|
||||
if (length > pos) {
|
||||
length -= pos;
|
||||
return buffers[i].constData() + pos;
|
||||
}
|
||||
pos -= length;
|
||||
}
|
||||
}
|
||||
|
||||
length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void free(qint64 bytes) {
|
||||
while (bytes > 0) {
|
||||
const qint64 blockSize = buffers.first().size() - head;
|
||||
|
||||
if (tailBuffer == 0 || blockSize > bytes) {
|
||||
// keep a single block around if it does not exceed
|
||||
// the basic block size, to avoid repeated allocations
|
||||
// between uses of the buffer
|
||||
if (bufferSize <= bytes) {
|
||||
if (buffers.first().size() <= basicBlockSize) {
|
||||
bufferSize = 0;
|
||||
head = tail = 0;
|
||||
} else {
|
||||
clear(); // try to minify/squeeze us
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
head += int(bytes);
|
||||
bufferSize -= bytes;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bufferSize -= blockSize;
|
||||
bytes -= blockSize;
|
||||
buffers.removeFirst();
|
||||
--tailBuffer;
|
||||
head = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline char *reserve(qint64 bytes) {
|
||||
if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
|
||||
return 0;
|
||||
|
||||
const qint64 newSize = bytes + tail;
|
||||
// if need buffer reallocation
|
||||
if (newSize > buffers.last().size()) {
|
||||
if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
|
||||
|| quint64(newSize) >= QByteArray::MaxSize)) {
|
||||
// shrink this buffer to its current size
|
||||
buffers.last().resize(tail);
|
||||
|
||||
// create a new QByteArray
|
||||
buffers.append(QByteArray());
|
||||
++tailBuffer;
|
||||
tail = 0;
|
||||
}
|
||||
buffers.last().resize(qMax(basicBlockSize, tail + int(bytes)));
|
||||
}
|
||||
|
||||
char *writePtr = buffers.last().data() + tail;
|
||||
bufferSize += bytes;
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
tail += int(bytes);
|
||||
return writePtr;
|
||||
}
|
||||
Q_CORE_EXPORT const char *readPointerAtPosition(qint64 pos, qint64 &length) const;
|
||||
Q_CORE_EXPORT void free(qint64 bytes);
|
||||
Q_CORE_EXPORT char *reserve(qint64 bytes);
|
||||
Q_CORE_EXPORT char *reserveFront(qint64 bytes);
|
||||
|
||||
inline void truncate(qint64 pos) {
|
||||
if (pos < size())
|
||||
chop(size() - pos);
|
||||
}
|
||||
|
||||
inline void chop(qint64 bytes) {
|
||||
while (bytes > 0) {
|
||||
if (tailBuffer == 0 || tail > bytes) {
|
||||
// keep a single block around if it does not exceed
|
||||
// the basic block size, to avoid repeated allocations
|
||||
// between uses of the buffer
|
||||
if (bufferSize <= bytes) {
|
||||
if (buffers.first().size() <= basicBlockSize) {
|
||||
bufferSize = 0;
|
||||
head = tail = 0;
|
||||
} else {
|
||||
clear(); // try to minify/squeeze us
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
|
||||
tail -= int(bytes);
|
||||
bufferSize -= bytes;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bufferSize -= tail;
|
||||
bytes -= tail;
|
||||
buffers.removeLast();
|
||||
--tailBuffer;
|
||||
tail = buffers.last().size();
|
||||
}
|
||||
}
|
||||
Q_CORE_EXPORT void chop(qint64 bytes);
|
||||
|
||||
inline bool isEmpty() const {
|
||||
return bufferSize == 0;
|
||||
@ -195,156 +95,36 @@ public:
|
||||
*ptr = c;
|
||||
}
|
||||
|
||||
inline void ungetChar(char c) {
|
||||
--head;
|
||||
if (head < 0) {
|
||||
if (bufferSize != 0) {
|
||||
buffers.prepend(QByteArray());
|
||||
++tailBuffer;
|
||||
} else {
|
||||
tail = basicBlockSize;
|
||||
}
|
||||
buffers.first().resize(basicBlockSize);
|
||||
head = basicBlockSize - 1;
|
||||
void ungetChar(char c)
|
||||
{
|
||||
if (head > 0) {
|
||||
--head;
|
||||
buffers.first()[head] = c;
|
||||
++bufferSize;
|
||||
} else {
|
||||
char *ptr = reserveFront(1);
|
||||
*ptr = c;
|
||||
}
|
||||
buffers.first()[head] = c;
|
||||
++bufferSize;
|
||||
}
|
||||
|
||||
|
||||
inline qint64 size() const {
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
buffers.erase(buffers.begin() + 1, buffers.end());
|
||||
buffers.first().clear();
|
||||
|
||||
head = tail = 0;
|
||||
tailBuffer = 0;
|
||||
bufferSize = 0;
|
||||
}
|
||||
|
||||
inline qint64 indexOf(char c) const {
|
||||
qint64 index = 0;
|
||||
qint64 j = head;
|
||||
for (int i = 0; i < buffers.size(); ++i) {
|
||||
const char *ptr = buffers[i].constData() + j;
|
||||
j = index + (i == tailBuffer ? tail : buffers[i].size()) - j;
|
||||
|
||||
while (index < j) {
|
||||
if (*ptr++ == c)
|
||||
return index;
|
||||
++index;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline qint64 indexOf(char c, qint64 maxLength) const {
|
||||
qint64 index = 0;
|
||||
qint64 j = head;
|
||||
for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
|
||||
const char *ptr = buffers[i].constData() + j;
|
||||
j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
|
||||
|
||||
while (index < j) {
|
||||
if (*ptr++ == c)
|
||||
return index;
|
||||
++index;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline qint64 read(char *data, qint64 maxLength) {
|
||||
const qint64 bytesToRead = qMin(size(), maxLength);
|
||||
qint64 readSoFar = 0;
|
||||
while (readSoFar < bytesToRead) {
|
||||
const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
|
||||
nextDataBlockSize());
|
||||
if (data)
|
||||
memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
|
||||
readSoFar += bytesToReadFromThisBlock;
|
||||
free(bytesToReadFromThisBlock);
|
||||
}
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
// read an unspecified amount (will read the first buffer)
|
||||
inline QByteArray read() {
|
||||
if (bufferSize == 0)
|
||||
return QByteArray();
|
||||
|
||||
QByteArray qba(buffers.takeFirst());
|
||||
|
||||
qba.reserve(0); // avoid that resizing needlessly reallocates
|
||||
if (tailBuffer == 0) {
|
||||
qba.resize(tail);
|
||||
tail = 0;
|
||||
buffers.append(QByteArray());
|
||||
} else {
|
||||
--tailBuffer;
|
||||
}
|
||||
qba.remove(0, head); // does nothing if head is 0
|
||||
head = 0;
|
||||
bufferSize -= qba.size();
|
||||
return qba;
|
||||
}
|
||||
|
||||
// peek the bytes from a specified position
|
||||
inline qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const
|
||||
{
|
||||
qint64 readSoFar = 0;
|
||||
|
||||
if (pos >= 0) {
|
||||
pos += head;
|
||||
for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) {
|
||||
qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size());
|
||||
|
||||
if (pos < blockLength) {
|
||||
blockLength = qMin(blockLength - pos, maxLength - readSoFar);
|
||||
memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength);
|
||||
readSoFar += blockLength;
|
||||
pos = 0;
|
||||
} else {
|
||||
pos -= blockLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
// append a new buffer to the end
|
||||
inline void append(const QByteArray &qba) {
|
||||
if (tail == 0) {
|
||||
buffers.last() = qba;
|
||||
} else {
|
||||
buffers.last().resize(tail);
|
||||
buffers.append(qba);
|
||||
++tailBuffer;
|
||||
}
|
||||
tail = qba.size();
|
||||
bufferSize += tail;
|
||||
}
|
||||
Q_CORE_EXPORT void clear();
|
||||
Q_CORE_EXPORT qint64 indexOf(char c) const;
|
||||
Q_CORE_EXPORT qint64 indexOf(char c, qint64 maxLength) const;
|
||||
Q_CORE_EXPORT qint64 read(char *data, qint64 maxLength);
|
||||
Q_CORE_EXPORT QByteArray read();
|
||||
Q_CORE_EXPORT qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const;
|
||||
Q_CORE_EXPORT void append(const QByteArray &qba);
|
||||
|
||||
inline qint64 skip(qint64 length) {
|
||||
return read(0, length);
|
||||
}
|
||||
|
||||
inline qint64 readLine(char *data, qint64 maxLength) {
|
||||
if (!data || --maxLength <= 0)
|
||||
return -1;
|
||||
|
||||
qint64 i = indexOf('\n', maxLength);
|
||||
i = read(data, i >= 0 ? (i + 1) : maxLength);
|
||||
|
||||
// Terminate it.
|
||||
data[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
Q_CORE_EXPORT qint64 readLine(char *data, qint64 maxLength);
|
||||
|
||||
inline bool canReadLine() const {
|
||||
return indexOf('\n') >= 0;
|
||||
|
@ -106,6 +106,7 @@ SOURCES += \
|
||||
tools/qrect.cpp \
|
||||
tools/qregexp.cpp \
|
||||
tools/qrefcount.cpp \
|
||||
tools/qringbuffer.cpp \
|
||||
tools/qshareddata.cpp \
|
||||
tools/qsharedpointer.cpp \
|
||||
tools/qsimd.cpp \
|
||||
|
@ -97,6 +97,7 @@ SOURCES += \
|
||||
../../corelib/tools/qlocale_tools.cpp \
|
||||
../../corelib/tools/qmap.cpp \
|
||||
../../corelib/tools/qregexp.cpp \
|
||||
../../corelib/tools/qringbuffer.cpp \
|
||||
../../corelib/tools/qpoint.cpp \
|
||||
../../corelib/tools/qrect.cpp \
|
||||
../../corelib/tools/qsize.cpp \
|
||||
|
@ -48,6 +48,7 @@ private slots:
|
||||
void sizeWhenReserved();
|
||||
void free();
|
||||
void reserveAndRead();
|
||||
void reserveFrontAndRead();
|
||||
void chop();
|
||||
void ungetChar();
|
||||
void indexOf();
|
||||
@ -219,6 +220,28 @@ void tst_QRingBuffer::reserveAndRead()
|
||||
QVERIFY(ringBuffer.size() == 0);
|
||||
}
|
||||
|
||||
void tst_QRingBuffer::reserveFrontAndRead()
|
||||
{
|
||||
QRingBuffer ringBuffer;
|
||||
// fill buffer with an arithmetic progression
|
||||
for (int i = 1; i < 256; ++i) {
|
||||
QByteArray ba(i, char(i));
|
||||
char *ringPos = ringBuffer.reserveFront(i);
|
||||
QVERIFY(ringPos);
|
||||
memcpy(ringPos, ba.constData(), i);
|
||||
}
|
||||
|
||||
// readback and check stored data
|
||||
for (int i = 255; i > 0; --i) {
|
||||
QByteArray ba;
|
||||
ba.resize(i);
|
||||
qint64 thisRead = ringBuffer.read(ba.data(), i);
|
||||
QCOMPARE(thisRead, qint64(i));
|
||||
QVERIFY(ba.count(char(i)) == i);
|
||||
}
|
||||
QVERIFY(ringBuffer.size() == 0);
|
||||
}
|
||||
|
||||
void tst_QRingBuffer::chop()
|
||||
{
|
||||
QRingBuffer ringBuffer;
|
||||
|
@ -48,6 +48,7 @@ OBJECTS = \
|
||||
qfsfileengine_win.o \
|
||||
qfsfileengine_iterator.o \
|
||||
qiodevice.o \
|
||||
qringbuffer.o \
|
||||
qdebug.o \
|
||||
qtextstream.o \
|
||||
qlogging.o \
|
||||
|
@ -47,6 +47,7 @@ OBJECTS = \
|
||||
qfsfileengine_win.obj \
|
||||
qfsfileengine_iterator.obj \
|
||||
qiodevice.obj \
|
||||
qringbuffer.obj \
|
||||
qdebug.obj \
|
||||
qtextstream.obj \
|
||||
qlogging.obj \
|
||||
@ -122,6 +123,7 @@ qfsfileengine.obj: $(CORESRC)\io\qfsfileengine.cpp $(PCH)
|
||||
qfsfileengine_win.obj: $(CORESRC)\io\qfsfileengine_win.cpp $(PCH)
|
||||
qfsfileengine_iterator.obj: $(CORESRC)\io\qfsfileengine_iterator.cpp $(PCH)
|
||||
qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
|
||||
qringbuffer.obj: $(CORESRC)\tools\qringbuffer.cpp $(PCH)
|
||||
qdebug.obj: $(CORESRC)\io\qdebug.cpp $(PCH)
|
||||
qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
|
||||
qtemporaryfile.obj: $(CORESRC)\io\qtemporaryfile.cpp $(PCH)
|
||||
|
@ -68,6 +68,7 @@ HEADERS = configureapp.h environment.h tools.h\
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qregexp.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qringbuffer_p.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstring.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.h \
|
||||
@ -119,6 +120,7 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qringbuffer.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstring_compat.cpp \
|
||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user