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
|
#qt code
|
||||||
QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
|
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 \
|
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 \
|
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 \
|
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/tools/qstring_compat.cpp \
|
||||||
$(SOURCE_PATH)/src/corelib/io/qfiledevice.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/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/io/qdebug.cpp \
|
||||||
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
|
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
|
||||||
$(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.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
|
qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
|
||||||
$(CXX) -c -o $@ $(CXXFLAGS) $(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
|
qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
|
||||||
$(CXX) -c -o $@ $(CXXFLAGS) $(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 \
|
qglobal.obj \
|
||||||
qhash.obj \
|
qhash.obj \
|
||||||
qiodevice.obj \
|
qiodevice.obj \
|
||||||
|
qringbuffer.obj \
|
||||||
qdebug.obj \
|
qdebug.obj \
|
||||||
qlist.obj \
|
qlist.obj \
|
||||||
qlinkedlist.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);
|
return bufferSize == 0 ? Q_NULLPTR : (buffers.first().constData() + head);
|
||||||
}
|
}
|
||||||
|
|
||||||
// access the bytes at a specified position
|
Q_CORE_EXPORT const char *readPointerAtPosition(qint64 pos, qint64 &length) const;
|
||||||
// the out-variable length will contain the amount of bytes readable
|
Q_CORE_EXPORT void free(qint64 bytes);
|
||||||
// from there, e.g. the amount still the same QByteArray
|
Q_CORE_EXPORT char *reserve(qint64 bytes);
|
||||||
inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
|
Q_CORE_EXPORT char *reserveFront(qint64 bytes);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void truncate(qint64 pos) {
|
inline void truncate(qint64 pos) {
|
||||||
if (pos < size())
|
if (pos < size())
|
||||||
chop(size() - pos);
|
chop(size() - pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void chop(qint64 bytes) {
|
Q_CORE_EXPORT 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isEmpty() const {
|
inline bool isEmpty() const {
|
||||||
return bufferSize == 0;
|
return bufferSize == 0;
|
||||||
@ -195,156 +95,36 @@ public:
|
|||||||
*ptr = c;
|
*ptr = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ungetChar(char c) {
|
void ungetChar(char c)
|
||||||
|
{
|
||||||
|
if (head > 0) {
|
||||||
--head;
|
--head;
|
||||||
if (head < 0) {
|
|
||||||
if (bufferSize != 0) {
|
|
||||||
buffers.prepend(QByteArray());
|
|
||||||
++tailBuffer;
|
|
||||||
} else {
|
|
||||||
tail = basicBlockSize;
|
|
||||||
}
|
|
||||||
buffers.first().resize(basicBlockSize);
|
|
||||||
head = basicBlockSize - 1;
|
|
||||||
}
|
|
||||||
buffers.first()[head] = c;
|
buffers.first()[head] = c;
|
||||||
++bufferSize;
|
++bufferSize;
|
||||||
|
} else {
|
||||||
|
char *ptr = reserveFront(1);
|
||||||
|
*ptr = c;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline qint64 size() const {
|
inline qint64 size() const {
|
||||||
return bufferSize;
|
return bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void clear() {
|
Q_CORE_EXPORT void clear();
|
||||||
buffers.erase(buffers.begin() + 1, buffers.end());
|
Q_CORE_EXPORT qint64 indexOf(char c) const;
|
||||||
buffers.first().clear();
|
Q_CORE_EXPORT qint64 indexOf(char c, qint64 maxLength) const;
|
||||||
|
Q_CORE_EXPORT qint64 read(char *data, qint64 maxLength);
|
||||||
head = tail = 0;
|
Q_CORE_EXPORT QByteArray read();
|
||||||
tailBuffer = 0;
|
Q_CORE_EXPORT qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const;
|
||||||
bufferSize = 0;
|
Q_CORE_EXPORT void append(const QByteArray &qba);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qint64 skip(qint64 length) {
|
inline qint64 skip(qint64 length) {
|
||||||
return read(0, length);
|
return read(0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline qint64 readLine(char *data, qint64 maxLength) {
|
Q_CORE_EXPORT 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool canReadLine() const {
|
inline bool canReadLine() const {
|
||||||
return indexOf('\n') >= 0;
|
return indexOf('\n') >= 0;
|
||||||
|
@ -106,6 +106,7 @@ SOURCES += \
|
|||||||
tools/qrect.cpp \
|
tools/qrect.cpp \
|
||||||
tools/qregexp.cpp \
|
tools/qregexp.cpp \
|
||||||
tools/qrefcount.cpp \
|
tools/qrefcount.cpp \
|
||||||
|
tools/qringbuffer.cpp \
|
||||||
tools/qshareddata.cpp \
|
tools/qshareddata.cpp \
|
||||||
tools/qsharedpointer.cpp \
|
tools/qsharedpointer.cpp \
|
||||||
tools/qsimd.cpp \
|
tools/qsimd.cpp \
|
||||||
|
@ -97,6 +97,7 @@ SOURCES += \
|
|||||||
../../corelib/tools/qlocale_tools.cpp \
|
../../corelib/tools/qlocale_tools.cpp \
|
||||||
../../corelib/tools/qmap.cpp \
|
../../corelib/tools/qmap.cpp \
|
||||||
../../corelib/tools/qregexp.cpp \
|
../../corelib/tools/qregexp.cpp \
|
||||||
|
../../corelib/tools/qringbuffer.cpp \
|
||||||
../../corelib/tools/qpoint.cpp \
|
../../corelib/tools/qpoint.cpp \
|
||||||
../../corelib/tools/qrect.cpp \
|
../../corelib/tools/qrect.cpp \
|
||||||
../../corelib/tools/qsize.cpp \
|
../../corelib/tools/qsize.cpp \
|
||||||
|
@ -48,6 +48,7 @@ private slots:
|
|||||||
void sizeWhenReserved();
|
void sizeWhenReserved();
|
||||||
void free();
|
void free();
|
||||||
void reserveAndRead();
|
void reserveAndRead();
|
||||||
|
void reserveFrontAndRead();
|
||||||
void chop();
|
void chop();
|
||||||
void ungetChar();
|
void ungetChar();
|
||||||
void indexOf();
|
void indexOf();
|
||||||
@ -219,6 +220,28 @@ void tst_QRingBuffer::reserveAndRead()
|
|||||||
QVERIFY(ringBuffer.size() == 0);
|
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()
|
void tst_QRingBuffer::chop()
|
||||||
{
|
{
|
||||||
QRingBuffer ringBuffer;
|
QRingBuffer ringBuffer;
|
||||||
|
@ -48,6 +48,7 @@ OBJECTS = \
|
|||||||
qfsfileengine_win.o \
|
qfsfileengine_win.o \
|
||||||
qfsfileengine_iterator.o \
|
qfsfileengine_iterator.o \
|
||||||
qiodevice.o \
|
qiodevice.o \
|
||||||
|
qringbuffer.o \
|
||||||
qdebug.o \
|
qdebug.o \
|
||||||
qtextstream.o \
|
qtextstream.o \
|
||||||
qlogging.o \
|
qlogging.o \
|
||||||
|
@ -47,6 +47,7 @@ OBJECTS = \
|
|||||||
qfsfileengine_win.obj \
|
qfsfileengine_win.obj \
|
||||||
qfsfileengine_iterator.obj \
|
qfsfileengine_iterator.obj \
|
||||||
qiodevice.obj \
|
qiodevice.obj \
|
||||||
|
qringbuffer.obj \
|
||||||
qdebug.obj \
|
qdebug.obj \
|
||||||
qtextstream.obj \
|
qtextstream.obj \
|
||||||
qlogging.obj \
|
qlogging.obj \
|
||||||
@ -122,6 +123,7 @@ qfsfileengine.obj: $(CORESRC)\io\qfsfileengine.cpp $(PCH)
|
|||||||
qfsfileengine_win.obj: $(CORESRC)\io\qfsfileengine_win.cpp $(PCH)
|
qfsfileengine_win.obj: $(CORESRC)\io\qfsfileengine_win.cpp $(PCH)
|
||||||
qfsfileengine_iterator.obj: $(CORESRC)\io\qfsfileengine_iterator.cpp $(PCH)
|
qfsfileengine_iterator.obj: $(CORESRC)\io\qfsfileengine_iterator.cpp $(PCH)
|
||||||
qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
|
qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
|
||||||
|
qringbuffer.obj: $(CORESRC)\tools\qringbuffer.cpp $(PCH)
|
||||||
qdebug.obj: $(CORESRC)\io\qdebug.cpp $(PCH)
|
qdebug.obj: $(CORESRC)\io\qdebug.cpp $(PCH)
|
||||||
qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
|
qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
|
||||||
qtemporaryfile.obj: $(CORESRC)\io\qtemporaryfile.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/qdatetime.h \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
|
$$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qregexp.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/qstring.h \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \
|
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.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/qdatetime.cpp \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
|
$$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qregexp.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.cpp \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qstring_compat.cpp \
|
$$QT_SOURCE_TREE/src/corelib/tools/qstring_compat.cpp \
|
||||||
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
|
$$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user