Add class QDebugStateSaver for writing QDebug operators correctly
Had to move QTextStreamPrivate to a private header, to be able to use its new internal Params struct from qdebug.cpp Change-Id: If28e25f27bbd04b1825a5eb3e2ef83ecad72e7b2 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
ad265c55be
commit
327b2ba3b7
@ -22,6 +22,7 @@ HEADERS += \
|
|||||||
io/qprocess.h \
|
io/qprocess.h \
|
||||||
io/qprocess_p.h \
|
io/qprocess_p.h \
|
||||||
io/qtextstream.h \
|
io/qtextstream.h \
|
||||||
|
io/qtextstream_p.h \
|
||||||
io/qtemporarydir.h \
|
io/qtemporarydir.h \
|
||||||
io/qtemporaryfile.h \
|
io/qtemporaryfile.h \
|
||||||
io/qtemporaryfile_p.h \
|
io/qtemporaryfile_p.h \
|
||||||
|
@ -47,6 +47,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "qdebug.h"
|
#include "qdebug.h"
|
||||||
|
#include <private/qtextstream_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
// This file is needed to force compilation of QDebug into the kernel library.
|
// This file is needed to force compilation of QDebug into the kernel library.
|
||||||
|
|
||||||
@ -170,6 +173,8 @@
|
|||||||
between writes.
|
between writes.
|
||||||
|
|
||||||
\since 5.0
|
\since 5.0
|
||||||
|
|
||||||
|
\sa QDebugStateSaver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -179,6 +184,8 @@
|
|||||||
automatic insertion of spaces is disabled.
|
automatic insertion of spaces is disabled.
|
||||||
|
|
||||||
\since 5.0
|
\since 5.0
|
||||||
|
|
||||||
|
\sa QDebugStateSaver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -321,3 +328,69 @@
|
|||||||
\fn QDebug &QDebug::operator<<(QTextStreamManipulator m)
|
\fn QDebug &QDebug::operator<<(QTextStreamManipulator m)
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QDebugStateSaver
|
||||||
|
|
||||||
|
\brief Convenience class for custom QDebug operators
|
||||||
|
|
||||||
|
Saves the settings used by QDebug, and restores them upon destruction.
|
||||||
|
|
||||||
|
The automatic insertion of spaces between writes is one of the settings
|
||||||
|
that QDebugStateSaver stores for the duration of the current block.
|
||||||
|
|
||||||
|
The settings of the internal QTextStream are also saved and restored,
|
||||||
|
so that using << hex in a QDebug operator doesn't affect other QDebug
|
||||||
|
operators.
|
||||||
|
|
||||||
|
\since 5.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QDebugStateSaverPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QDebugStateSaverPrivate(QDebug &dbg)
|
||||||
|
: m_dbg(dbg),
|
||||||
|
m_spaces(dbg.autoInsertSpaces()),
|
||||||
|
m_streamParams(dbg.stream->ts.d_ptr->params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void restoreState()
|
||||||
|
{
|
||||||
|
m_dbg.setAutoInsertSpaces(m_spaces);
|
||||||
|
m_dbg.stream->ts.d_ptr->params = m_streamParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug &m_dbg;
|
||||||
|
|
||||||
|
// QDebug state
|
||||||
|
const bool m_spaces;
|
||||||
|
|
||||||
|
// QTextStream state
|
||||||
|
const QTextStreamPrivate::Params m_streamParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a QDebugStateSaver instance, which saves the settings
|
||||||
|
currently used by \a dbg.
|
||||||
|
|
||||||
|
\sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces()
|
||||||
|
*/
|
||||||
|
QDebugStateSaver::QDebugStateSaver(QDebug &dbg)
|
||||||
|
: d(new QDebugStateSaverPrivate(dbg))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destroyes a QDebugStateSaver instance, which restores the settings
|
||||||
|
used by \a dbg when the QDebugStateSaver instance was created.
|
||||||
|
|
||||||
|
\sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces()
|
||||||
|
*/
|
||||||
|
QDebugStateSaver::~QDebugStateSaver()
|
||||||
|
{
|
||||||
|
d->restoreState();
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class Q_CORE_EXPORT QDebug
|
class Q_CORE_EXPORT QDebug
|
||||||
{
|
{
|
||||||
friend class QMessageLogger;
|
friend class QMessageLogger;
|
||||||
|
friend class QDebugStateSaverPrivate;
|
||||||
struct Stream {
|
struct Stream {
|
||||||
Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
|
Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
|
||||||
Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
|
Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {}
|
||||||
@ -132,6 +133,17 @@ public:
|
|||||||
|
|
||||||
Q_DECLARE_SHARED(QDebug)
|
Q_DECLARE_SHARED(QDebug)
|
||||||
|
|
||||||
|
class QDebugStateSaverPrivate;
|
||||||
|
class Q_CORE_EXPORT QDebugStateSaver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QDebugStateSaver(QDebug &dbg);
|
||||||
|
~QDebugStateSaver();
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(QDebugStateSaver)
|
||||||
|
QScopedPointer<QDebugStateSaverPrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
class QNoDebug
|
class QNoDebug
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -226,12 +226,10 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qtextstream.h"
|
#include "qtextstream.h"
|
||||||
|
#include "private/qtextstream_p.h"
|
||||||
#include "qbuffer.h"
|
#include "qbuffer.h"
|
||||||
#include "qfile.h"
|
#include "qfile.h"
|
||||||
#include "qnumeric.h"
|
#include "qnumeric.h"
|
||||||
#ifndef QT_NO_TEXTCODEC
|
|
||||||
#include "qtextcodec.h"
|
|
||||||
#endif
|
|
||||||
#ifndef Q_OS_WINCE
|
#ifndef Q_OS_WINCE
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
@ -315,119 +313,7 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
|
||||||
class QDeviceClosedNotifier : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
inline QDeviceClosedNotifier()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
inline void setupDevice(QTextStream *stream, QIODevice *device)
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
if (device)
|
|
||||||
connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
|
|
||||||
this->stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
inline void flushStream() { stream->flush(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QTextStream *stream;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
class QTextStreamPrivate
|
|
||||||
{
|
|
||||||
Q_DECLARE_PUBLIC(QTextStream)
|
|
||||||
public:
|
|
||||||
QTextStreamPrivate(QTextStream *q_ptr);
|
|
||||||
~QTextStreamPrivate();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
// device
|
|
||||||
QIODevice *device;
|
|
||||||
#ifndef QT_NO_QOBJECT
|
|
||||||
QDeviceClosedNotifier deviceClosedNotifier;
|
|
||||||
#endif
|
|
||||||
bool deleteDevice;
|
|
||||||
|
|
||||||
// string
|
|
||||||
QString *string;
|
|
||||||
int stringOffset;
|
|
||||||
QIODevice::OpenMode stringOpenMode;
|
|
||||||
|
|
||||||
#ifndef QT_NO_TEXTCODEC
|
|
||||||
// codec
|
|
||||||
QTextCodec *codec;
|
|
||||||
QTextCodec::ConverterState readConverterState;
|
|
||||||
QTextCodec::ConverterState writeConverterState;
|
|
||||||
QTextCodec::ConverterState *readConverterSavedState;
|
|
||||||
bool autoDetectUnicode;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// i/o
|
|
||||||
enum TokenDelimiter {
|
|
||||||
Space,
|
|
||||||
NotSpace,
|
|
||||||
EndOfLine
|
|
||||||
};
|
|
||||||
|
|
||||||
QString read(int maxlen);
|
|
||||||
bool scan(const QChar **ptr, int *tokenLength,
|
|
||||||
int maxlen, TokenDelimiter delimiter);
|
|
||||||
inline const QChar *readPtr() const;
|
|
||||||
inline void consumeLastToken();
|
|
||||||
inline void consume(int nchars);
|
|
||||||
void saveConverterState(qint64 newPos);
|
|
||||||
void restoreToSavedConverterState();
|
|
||||||
int lastTokenSize;
|
|
||||||
|
|
||||||
// Return value type for getNumber()
|
|
||||||
enum NumberParsingStatus {
|
|
||||||
npsOk,
|
|
||||||
npsMissingDigit,
|
|
||||||
npsInvalidPrefix
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool getChar(QChar *ch);
|
|
||||||
inline void ungetChar(QChar ch);
|
|
||||||
NumberParsingStatus getNumber(qulonglong *l);
|
|
||||||
bool getReal(double *f);
|
|
||||||
|
|
||||||
inline void write(const QString &data);
|
|
||||||
inline void putString(const QString &ch, bool number = false);
|
|
||||||
void putNumber(qulonglong number, bool negative);
|
|
||||||
|
|
||||||
// buffers
|
|
||||||
bool fillReadBuffer(qint64 maxBytes = -1);
|
|
||||||
void resetReadBuffer();
|
|
||||||
void flushWriteBuffer();
|
|
||||||
QString writeBuffer;
|
|
||||||
QString readBuffer;
|
|
||||||
int readBufferOffset;
|
|
||||||
int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
|
|
||||||
qint64 readBufferStartDevicePos;
|
|
||||||
|
|
||||||
// streaming parameters
|
|
||||||
int realNumberPrecision;
|
|
||||||
int integerBase;
|
|
||||||
int fieldWidth;
|
|
||||||
QChar padChar;
|
|
||||||
QTextStream::FieldAlignment fieldAlignment;
|
|
||||||
QTextStream::RealNumberNotation realNumberNotation;
|
|
||||||
QTextStream::NumberFlags numberFlags;
|
|
||||||
|
|
||||||
// status
|
|
||||||
QTextStream::Status status;
|
|
||||||
|
|
||||||
QLocale locale;
|
|
||||||
|
|
||||||
QTextStream *q_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
@ -481,10 +367,7 @@ static void copyConverterStateHelper(QTextCodec::ConverterState *dest,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*!
|
void QTextStreamPrivate::Params::reset()
|
||||||
\internal
|
|
||||||
*/
|
|
||||||
void QTextStreamPrivate::reset()
|
|
||||||
{
|
{
|
||||||
realNumberPrecision = 6;
|
realNumberPrecision = 6;
|
||||||
integerBase = 0;
|
integerBase = 0;
|
||||||
@ -493,6 +376,14 @@ void QTextStreamPrivate::reset()
|
|||||||
fieldAlignment = QTextStream::AlignRight;
|
fieldAlignment = QTextStream::AlignRight;
|
||||||
realNumberNotation = QTextStream::SmartNotation;
|
realNumberNotation = QTextStream::SmartNotation;
|
||||||
numberFlags = 0;
|
numberFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
void QTextStreamPrivate::reset()
|
||||||
|
{
|
||||||
|
params.reset();
|
||||||
|
|
||||||
device = 0;
|
device = 0;
|
||||||
deleteDevice = false;
|
deleteDevice = false;
|
||||||
@ -985,15 +876,17 @@ inline void QTextStreamPrivate::putString(const QString &s, bool number)
|
|||||||
QString tmp = s;
|
QString tmp = s;
|
||||||
|
|
||||||
// handle padding
|
// handle padding
|
||||||
int padSize = fieldWidth - s.size();
|
int padSize = params.fieldWidth - s.size();
|
||||||
if (padSize > 0) {
|
if (padSize > 0) {
|
||||||
QString pad(padSize, padChar);
|
QString pad(padSize, params.padChar);
|
||||||
if (fieldAlignment == QTextStream::AlignLeft) {
|
switch (params.fieldAlignment) {
|
||||||
tmp.append(QString(padSize, padChar));
|
case QTextStream::AlignLeft:
|
||||||
} else if (fieldAlignment == QTextStream::AlignRight
|
tmp.append(pad);
|
||||||
|| fieldAlignment == QTextStream::AlignAccountingStyle) {
|
break;
|
||||||
tmp.prepend(QString(padSize, padChar));
|
case QTextStream::AlignRight:
|
||||||
if (fieldAlignment == QTextStream::AlignAccountingStyle && number) {
|
case QTextStream::AlignAccountingStyle:
|
||||||
|
tmp.prepend(pad);
|
||||||
|
if (params.fieldAlignment == QTextStream::AlignAccountingStyle && number) {
|
||||||
const QChar sign = s.size() > 0 ? s.at(0) : QChar();
|
const QChar sign = s.size() > 0 ? s.at(0) : QChar();
|
||||||
if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
|
if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
|
||||||
QChar *data = tmp.data();
|
QChar *data = tmp.data();
|
||||||
@ -1001,9 +894,11 @@ inline void QTextStreamPrivate::putString(const QString &s, bool number)
|
|||||||
data[0] = sign;
|
data[0] = sign;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (fieldAlignment == QTextStream::AlignCenter) {
|
break;
|
||||||
tmp.prepend(QString(padSize/2, padChar));
|
case QTextStream::AlignCenter:
|
||||||
tmp.append(QString(padSize - padSize/2, padChar));
|
tmp.prepend(QString(padSize/2, params.padChar));
|
||||||
|
tmp.append(QString(padSize - padSize/2, params.padChar));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,13 +1070,7 @@ void QTextStream::reset()
|
|||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
|
|
||||||
d->realNumberPrecision = 6;
|
d->params.reset();
|
||||||
d->integerBase = 0;
|
|
||||||
d->fieldWidth = 0;
|
|
||||||
d->padChar = QLatin1Char(' ');
|
|
||||||
d->fieldAlignment = QTextStream::AlignRight;
|
|
||||||
d->realNumberNotation = QTextStream::SmartNotation;
|
|
||||||
d->numberFlags = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1400,7 +1289,7 @@ QString *QTextStream::string() const
|
|||||||
void QTextStream::setFieldAlignment(FieldAlignment mode)
|
void QTextStream::setFieldAlignment(FieldAlignment mode)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->fieldAlignment = mode;
|
d->params.fieldAlignment = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1411,7 +1300,7 @@ void QTextStream::setFieldAlignment(FieldAlignment mode)
|
|||||||
QTextStream::FieldAlignment QTextStream::fieldAlignment() const
|
QTextStream::FieldAlignment QTextStream::fieldAlignment() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->fieldAlignment;
|
return d->params.fieldAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1432,7 +1321,7 @@ QTextStream::FieldAlignment QTextStream::fieldAlignment() const
|
|||||||
void QTextStream::setPadChar(QChar ch)
|
void QTextStream::setPadChar(QChar ch)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->padChar = ch;
|
d->params.padChar = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1443,7 +1332,7 @@ void QTextStream::setPadChar(QChar ch)
|
|||||||
QChar QTextStream::padChar() const
|
QChar QTextStream::padChar() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->padChar;
|
return d->params.padChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1461,7 +1350,7 @@ QChar QTextStream::padChar() const
|
|||||||
void QTextStream::setFieldWidth(int width)
|
void QTextStream::setFieldWidth(int width)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->fieldWidth = width;
|
d->params.fieldWidth = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1472,7 +1361,7 @@ void QTextStream::setFieldWidth(int width)
|
|||||||
int QTextStream::fieldWidth() const
|
int QTextStream::fieldWidth() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->fieldWidth;
|
return d->params.fieldWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1486,7 +1375,7 @@ int QTextStream::fieldWidth() const
|
|||||||
void QTextStream::setNumberFlags(NumberFlags flags)
|
void QTextStream::setNumberFlags(NumberFlags flags)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->numberFlags = flags;
|
d->params.numberFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1497,7 +1386,7 @@ void QTextStream::setNumberFlags(NumberFlags flags)
|
|||||||
QTextStream::NumberFlags QTextStream::numberFlags() const
|
QTextStream::NumberFlags QTextStream::numberFlags() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->numberFlags;
|
return d->params.numberFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1513,7 +1402,7 @@ QTextStream::NumberFlags QTextStream::numberFlags() const
|
|||||||
void QTextStream::setIntegerBase(int base)
|
void QTextStream::setIntegerBase(int base)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->integerBase = base;
|
d->params.integerBase = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1525,7 +1414,7 @@ void QTextStream::setIntegerBase(int base)
|
|||||||
int QTextStream::integerBase() const
|
int QTextStream::integerBase() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->integerBase;
|
return d->params.integerBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1539,7 +1428,7 @@ int QTextStream::integerBase() const
|
|||||||
void QTextStream::setRealNumberNotation(RealNumberNotation notation)
|
void QTextStream::setRealNumberNotation(RealNumberNotation notation)
|
||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
d->realNumberNotation = notation;
|
d->params.realNumberNotation = notation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1550,7 +1439,7 @@ void QTextStream::setRealNumberNotation(RealNumberNotation notation)
|
|||||||
QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
|
QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->realNumberNotation;
|
return d->params.realNumberNotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1567,10 +1456,10 @@ void QTextStream::setRealNumberPrecision(int precision)
|
|||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
if (precision < 0) {
|
if (precision < 0) {
|
||||||
qWarning("QTextStream::setRealNumberPrecision: Invalid precision (%d)", precision);
|
qWarning("QTextStream::setRealNumberPrecision: Invalid precision (%d)", precision);
|
||||||
d->realNumberPrecision = 6;
|
d->params.realNumberPrecision = 6;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->realNumberPrecision = precision;
|
d->params.realNumberPrecision = precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1582,7 +1471,7 @@ void QTextStream::setRealNumberPrecision(int precision)
|
|||||||
int QTextStream::realNumberPrecision() const
|
int QTextStream::realNumberPrecision() const
|
||||||
{
|
{
|
||||||
Q_D(const QTextStream);
|
Q_D(const QTextStream);
|
||||||
return d->realNumberPrecision;
|
return d->params.realNumberPrecision;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1722,7 +1611,7 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
|
|||||||
consumeLastToken();
|
consumeLastToken();
|
||||||
|
|
||||||
// detect int encoding
|
// detect int encoding
|
||||||
int base = integerBase;
|
int base = params.integerBase;
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
QChar ch;
|
QChar ch;
|
||||||
if (!getChar(&ch))
|
if (!getChar(&ch))
|
||||||
@ -2300,6 +2189,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
|
|||||||
QString result;
|
QString result;
|
||||||
|
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
|
const QTextStream::NumberFlags numberFlags = params.numberFlags;
|
||||||
if (numberFlags & QTextStream::ShowBase)
|
if (numberFlags & QTextStream::ShowBase)
|
||||||
flags |= QLocalePrivate::ShowBase;
|
flags |= QLocalePrivate::ShowBase;
|
||||||
if (numberFlags & QTextStream::ForceSign)
|
if (numberFlags & QTextStream::ForceSign)
|
||||||
@ -2315,7 +2205,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
|
|||||||
flags |= QLocalePrivate::ThousandsGroup;
|
flags |= QLocalePrivate::ThousandsGroup;
|
||||||
|
|
||||||
const QLocalePrivate *dd = locale.d;
|
const QLocalePrivate *dd = locale.d;
|
||||||
int base = integerBase ? integerBase : 10;
|
int base = params.integerBase ? params.integerBase : 10;
|
||||||
if (negative && base == 10) {
|
if (negative && base == 10) {
|
||||||
result = dd->longLongToString(-static_cast<qlonglong>(number), -1,
|
result = dd->longLongToString(-static_cast<qlonglong>(number), -1,
|
||||||
base, -1, flags);
|
base, -1, flags);
|
||||||
@ -2330,7 +2220,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
|
|||||||
result = dd->unsLongLongToString(number, -1, base, -1, flags);
|
result = dd->unsLongLongToString(number, -1, base, -1, flags);
|
||||||
// workaround for backward compatibility - in octal form with
|
// workaround for backward compatibility - in octal form with
|
||||||
// ShowBase flag set zero should be written as '00'
|
// ShowBase flag set zero should be written as '00'
|
||||||
if (number == 0 && base == 8 && numberFlags & QTextStream::ShowBase
|
if (number == 0 && base == 8 && params.numberFlags & QTextStream::ShowBase
|
||||||
&& result == QLatin1String("0")) {
|
&& result == QLatin1String("0")) {
|
||||||
result.prepend(QLatin1Char('0'));
|
result.prepend(QLatin1Char('0'));
|
||||||
}
|
}
|
||||||
@ -2524,7 +2414,7 @@ QTextStream &QTextStream::operator<<(double f)
|
|||||||
flags |= QLocalePrivate::Alternate;
|
flags |= QLocalePrivate::Alternate;
|
||||||
|
|
||||||
const QLocalePrivate *dd = d->locale.d;
|
const QLocalePrivate *dd = d->locale.d;
|
||||||
QString num = dd->doubleToString(f, d->realNumberPrecision, form, -1, flags);
|
QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
|
||||||
d->putString(num, true);
|
d->putString(num, true);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -2605,13 +2495,13 @@ QTextStream &QTextStream::operator<<(const void *ptr)
|
|||||||
{
|
{
|
||||||
Q_D(QTextStream);
|
Q_D(QTextStream);
|
||||||
CHECK_VALID_STREAM(*this);
|
CHECK_VALID_STREAM(*this);
|
||||||
int oldBase = d->integerBase;
|
const int oldBase = d->params.integerBase;
|
||||||
NumberFlags oldFlags = d->numberFlags;
|
const NumberFlags oldFlags = d->params.numberFlags;
|
||||||
d->integerBase = 16;
|
d->params.integerBase = 16;
|
||||||
d->numberFlags |= ShowBase;
|
d->params.numberFlags |= ShowBase;
|
||||||
d->putNumber(reinterpret_cast<quintptr>(ptr), false);
|
d->putNumber(reinterpret_cast<quintptr>(ptr), false);
|
||||||
d->integerBase = oldBase;
|
d->params.integerBase = oldBase;
|
||||||
d->numberFlags = oldFlags;
|
d->params.numberFlags = oldFlags;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3130,7 +3020,3 @@ QLocale QTextStream::locale() const
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
|
||||||
#include "qtextstream.moc"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -194,6 +194,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QTextStream)
|
Q_DISABLE_COPY(QTextStream)
|
||||||
|
friend class QDebugStateSaverPrivate;
|
||||||
|
|
||||||
QScopedPointer<QTextStreamPrivate> d_ptr;
|
QScopedPointer<QTextStreamPrivate> d_ptr;
|
||||||
};
|
};
|
||||||
|
185
src/corelib/io/qtextstream_p.h
Normal file
185
src/corelib/io/qtextstream_p.h
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** 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 Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/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 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3.0 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTEXTSTREAM_P_H
|
||||||
|
#define QTEXTSTREAM_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qtextstream.h"
|
||||||
|
#ifndef QT_NO_TEXTCODEC
|
||||||
|
#include "qtextcodec.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#ifndef QT_NO_QOBJECT
|
||||||
|
class QDeviceClosedNotifier : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
inline QDeviceClosedNotifier()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
inline void setupDevice(QTextStream *stream, QIODevice *device)
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
if (device)
|
||||||
|
connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
|
||||||
|
this->stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
inline void flushStream() { stream->flush(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextStream *stream;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QTextStreamPrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QTextStream)
|
||||||
|
public:
|
||||||
|
QTextStreamPrivate(QTextStream *q_ptr);
|
||||||
|
~QTextStreamPrivate();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
// device
|
||||||
|
QIODevice *device;
|
||||||
|
#ifndef QT_NO_QOBJECT
|
||||||
|
QDeviceClosedNotifier deviceClosedNotifier;
|
||||||
|
#endif
|
||||||
|
bool deleteDevice;
|
||||||
|
|
||||||
|
// string
|
||||||
|
QString *string;
|
||||||
|
int stringOffset;
|
||||||
|
QIODevice::OpenMode stringOpenMode;
|
||||||
|
|
||||||
|
#ifndef QT_NO_TEXTCODEC
|
||||||
|
// codec
|
||||||
|
QTextCodec *codec;
|
||||||
|
QTextCodec::ConverterState readConverterState;
|
||||||
|
QTextCodec::ConverterState writeConverterState;
|
||||||
|
QTextCodec::ConverterState *readConverterSavedState;
|
||||||
|
bool autoDetectUnicode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// i/o
|
||||||
|
enum TokenDelimiter {
|
||||||
|
Space,
|
||||||
|
NotSpace,
|
||||||
|
EndOfLine
|
||||||
|
};
|
||||||
|
|
||||||
|
QString read(int maxlen);
|
||||||
|
bool scan(const QChar **ptr, int *tokenLength,
|
||||||
|
int maxlen, TokenDelimiter delimiter);
|
||||||
|
inline const QChar *readPtr() const;
|
||||||
|
inline void consumeLastToken();
|
||||||
|
inline void consume(int nchars);
|
||||||
|
void saveConverterState(qint64 newPos);
|
||||||
|
void restoreToSavedConverterState();
|
||||||
|
int lastTokenSize;
|
||||||
|
|
||||||
|
// Return value type for getNumber()
|
||||||
|
enum NumberParsingStatus {
|
||||||
|
npsOk,
|
||||||
|
npsMissingDigit,
|
||||||
|
npsInvalidPrefix
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool getChar(QChar *ch);
|
||||||
|
inline void ungetChar(QChar ch);
|
||||||
|
NumberParsingStatus getNumber(qulonglong *l);
|
||||||
|
bool getReal(double *f);
|
||||||
|
|
||||||
|
inline void write(const QString &data);
|
||||||
|
inline void putString(const QString &ch, bool number = false);
|
||||||
|
void putNumber(qulonglong number, bool negative);
|
||||||
|
|
||||||
|
// buffers
|
||||||
|
bool fillReadBuffer(qint64 maxBytes = -1);
|
||||||
|
void resetReadBuffer();
|
||||||
|
void flushWriteBuffer();
|
||||||
|
QString writeBuffer;
|
||||||
|
QString readBuffer;
|
||||||
|
int readBufferOffset;
|
||||||
|
int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
|
||||||
|
qint64 readBufferStartDevicePos;
|
||||||
|
|
||||||
|
// streaming parameters
|
||||||
|
class Params
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
int realNumberPrecision;
|
||||||
|
int integerBase;
|
||||||
|
int fieldWidth;
|
||||||
|
QChar padChar;
|
||||||
|
QTextStream::FieldAlignment fieldAlignment;
|
||||||
|
QTextStream::RealNumberNotation realNumberNotation;
|
||||||
|
QTextStream::NumberFlags numberFlags;
|
||||||
|
};
|
||||||
|
Params params;
|
||||||
|
|
||||||
|
// status
|
||||||
|
QTextStream::Status status;
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
|
||||||
|
QTextStream *q_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QTEXTSTREAM_P_H
|
@ -52,7 +52,8 @@ private slots:
|
|||||||
void warningWithoutDebug() const;
|
void warningWithoutDebug() const;
|
||||||
void criticalWithoutDebug() const;
|
void criticalWithoutDebug() const;
|
||||||
void debugWithBool() const;
|
void debugWithBool() const;
|
||||||
void debugNoSpaces() const;
|
void debugSpaceHandling() const;
|
||||||
|
void stateSaver() const;
|
||||||
void veryLongWarningMessage() const;
|
void veryLongWarningMessage() const;
|
||||||
void qDebugQStringRef() const;
|
void qDebugQStringRef() const;
|
||||||
void qDebugQLatin1String() const;
|
void qDebugQLatin1String() const;
|
||||||
@ -150,7 +151,36 @@ void tst_QDebug::debugWithBool() const
|
|||||||
QCOMPARE(QString::fromLatin1(s_function), function);
|
QCOMPARE(QString::fromLatin1(s_function), function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QDebug::debugNoSpaces() const
|
class MyPoint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyPoint(int val1, int val2)
|
||||||
|
: v1(val1), v2(val2) {}
|
||||||
|
int v1;
|
||||||
|
int v2;
|
||||||
|
};
|
||||||
|
QDebug operator<< (QDebug s, const MyPoint& point)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver saver(s);
|
||||||
|
return s.nospace() << "MyPoint(" << point.v1 << ", " << point.v2 << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyLine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyLine(const MyPoint& point1, const MyPoint& point2)
|
||||||
|
: p1(point1), p2(point2) {}
|
||||||
|
MyPoint p1;
|
||||||
|
MyPoint p2;
|
||||||
|
};
|
||||||
|
QDebug operator<< (QDebug s, const MyLine& line)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver saver(s);
|
||||||
|
s.nospace() << "MyLine(" << line.p1 << ", " << line.p2 << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDebug::debugSpaceHandling() const
|
||||||
{
|
{
|
||||||
MessageHandlerSetter mhs(myMessageHandler);
|
MessageHandlerSetter mhs(myMessageHandler);
|
||||||
{
|
{
|
||||||
@ -166,8 +196,26 @@ void tst_QDebug::debugNoSpaces() const
|
|||||||
d << "key=" << "value";
|
d << "key=" << "value";
|
||||||
d.space();
|
d.space();
|
||||||
d << 1 << 2;
|
d << 1 << 2;
|
||||||
|
MyLine line(MyPoint(10, 11), MyPoint (12, 13));
|
||||||
|
d << line;
|
||||||
|
// With the old implementation of MyPoint doing dbg.nospace() << ...; dbg.space() we ended up with
|
||||||
|
// MyLine(MyPoint(10, 11) , MyPoint(12, 13) )
|
||||||
}
|
}
|
||||||
QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 "));
|
QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 MyLine(MyPoint(10, 11), MyPoint(12, 13))"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDebug::stateSaver() const
|
||||||
|
{
|
||||||
|
MessageHandlerSetter mhs(myMessageHandler);
|
||||||
|
{
|
||||||
|
QDebug d = qDebug();
|
||||||
|
{
|
||||||
|
QDebugStateSaver saver(d);
|
||||||
|
d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
|
||||||
|
}
|
||||||
|
d.space() << 42;
|
||||||
|
}
|
||||||
|
QCOMPARE(s_msg, QString::fromLatin1("02a 42 "));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QDebug::veryLongWarningMessage() const
|
void tst_QDebug::veryLongWarningMessage() const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user