Fix regression in QXmlStreamWriter with codec set to UTF-16

Actually, this broke using QXmlStreamWriter with any codec
where characters in the ASCII range have a different encoding
than the ASCII standard.

This was a regression from 558fe9383ba0aecbec09cc411c0ebab132aac137

Task-number: QTBUG-23310

Change-Id: I75bd013e9d5de53da564a76c2f06e95ff35303a8
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
Jan Arve Saether 2012-11-20 11:11:44 +01:00 committed by The Qt Project
parent 4532a1399e
commit 035d93a6e1
2 changed files with 47 additions and 7 deletions

View File

@ -2980,6 +2980,7 @@ public:
uint wroteSomething :1;
uint hasError :1;
uint autoFormatting :1;
uint isCodecASCIICompatible :1;
QByteArray autoFormattingIndent;
NamespaceDeclaration emptyNamespace;
int lastNamespaceDeclaration;
@ -2988,6 +2989,7 @@ public:
QTextCodec *codec;
QTextEncoder *encoder;
#endif
void checkIfASCIICompatibleCodec();
NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
@ -3009,6 +3011,7 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
codec = QTextCodec::codecForMib(106); // utf8
encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
#endif
checkIfASCIICompatibleCodec();
inStartElement = inEmptyElement = false;
wroteSomething = false;
hasError = false;
@ -3018,6 +3021,18 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
namespacePrefixCount = 0;
}
void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec()
{
#ifndef QT_NO_TEXTCODEC
Q_ASSERT(encoder);
// assumes ASCII-compatibility for all 8-bit encodings
const QByteArray bytes = encoder->fromUnicode(QStringLiteral(" "));
isCodecASCIICompatible = (bytes.count() == 1);
#else
isCodecASCIICompatible = true;
#endif
}
void QXmlStreamWriterPrivate::write(const QStringRef &s)
{
if (device) {
@ -3086,18 +3101,20 @@ void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespa
write(escaped);
}
// ASCII only!
// Converts from ASCII to output encoding
void QXmlStreamWriterPrivate::write(const char *s, int len)
{
if (device) {
if (hasError)
return;
if (device->write(s, len) != len)
hasError = true;
} else if (stringDevice) {
stringDevice->append(QString::fromLatin1(s, len));
} else
qWarning("QXmlStreamWriter: No device");
if (isCodecASCIICompatible) {
if (device->write(s, len) != len)
hasError = true;
return;
}
}
write(QString::fromLatin1(s, len));
}
void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
@ -3279,6 +3296,7 @@ void QXmlStreamWriter::setCodec(QTextCodec *codec)
d->codec = codec;
delete d->encoder;
d->encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
d->checkIfASCIICompatibleCodec();
}
}

View File

@ -558,6 +558,7 @@ private slots:
void hasAttribute() const;
void writeWithCodec() const;
void writeWithUtf8Codec() const;
void writeWithUtf16Codec() const;
void writeWithStandalone() const;
void entitiesAndWhitespace_1() const;
void entitiesAndWhitespace_2() const;
@ -1279,6 +1280,27 @@ void tst_QXmlStream::writeWithUtf8Codec() const
QVERIFY(outarray.startsWith(begin));
}
void tst_QXmlStream::writeWithUtf16Codec() const
{
QByteArray outarray;
QXmlStreamWriter writer(&outarray);
QTextCodec *codec = QTextCodec::codecForMib(1014); // utf-16LE
QVERIFY(codec);
writer.setCodec(codec);
writer.writeStartDocument("1.0");
static const char begin[] = "<?xml version=\"1.0\" encoding=\"UTF-16"; // skip potential "LE" suffix
const int count = sizeof(begin) - 1; // don't include 0 terminator
QByteArray begin_UTF16;
begin_UTF16.reserve(2*(count));
for (int i = 0; i < count; ++i) {
begin_UTF16.append(begin[i]);
begin_UTF16.append((char)'\0');
}
QVERIFY(outarray.startsWith(begin_UTF16));
}
void tst_QXmlStream::writeWithStandalone() const
{
{