diff options
author | Kevin Wu Won <kevin.wu-won@nokia.com> | 2010-10-12 14:52:31 +1000 |
---|---|---|
committer | Kevin Wu Won <kevin.wu-won@nokia.com> | 2010-10-12 15:24:00 +1000 |
commit | ce598790f41edfcb8439833ddf6f4967996ee576 (patch) | |
tree | 74b722c1926726402824a886053f8a8519288ea3 | |
parent | 72e8ff3f6579e661443c33a882a138384df46a04 (diff) |
Speed up QVersitWriter 2.5x
Avoid round-tripping through Unicode for base-64 encoded data, on
ASCII-compatible codecs
-rw-r--r-- | src/versit/qvcard21writer.cpp | 11 | ||||
-rw-r--r-- | src/versit/qvcard30writer.cpp | 12 | ||||
-rw-r--r-- | src/versit/qversitdocumentwriter_p.cpp | 30 | ||||
-rw-r--r-- | src/versit/qversitdocumentwriter_p.h | 1 |
4 files changed, 50 insertions, 4 deletions
diff --git a/src/versit/qvcard21writer.cpp b/src/versit/qvcard21writer.cpp index 1f987d1611..31bbdd46be 100644 --- a/src/versit/qvcard21writer.cpp +++ b/src/versit/qvcard21writer.cpp @@ -67,6 +67,7 @@ void QVCard21Writer::encodeVersitProperty(const QVersitProperty& property) QVariant variant(property.variantValue()); QString renderedValue; + QByteArray renderedBytes; bool useUtf8 = false; /* Structured values need to have their components backslash-escaped (in vCard 2.1, semicolons @@ -102,7 +103,10 @@ void QVCard21Writer::encodeVersitProperty(const QVersitProperty& property) useUtf8 = encodeVersitValue(parameters, renderedValue); } else if (variant.type() == QVariant::ByteArray) { parameters.insert(QLatin1String("ENCODING"), QLatin1String("BASE64")); - renderedValue = QLatin1String(variant.toByteArray().toBase64().data()); + if (mCodecIsAsciiCompatible) // optimize by not converting to unicode + renderedBytes = variant.toByteArray().toBase64(); + else + renderedValue = QLatin1String(variant.toByteArray().toBase64().data()); } // Encode parameters @@ -121,7 +125,10 @@ void QVCard21Writer::encodeVersitProperty(const QVersitProperty& property) // one extra line break after the value are needed in vCard 2.1 writeCrlf(); writeString(QLatin1String(" ")); - writeString(renderedValue, useUtf8); + if (renderedBytes.isEmpty()) + writeString(renderedValue, useUtf8); + else + writeBytes(renderedBytes); writeCrlf(); } writeCrlf(); diff --git a/src/versit/qvcard30writer.cpp b/src/versit/qvcard30writer.cpp index 97ccc7a7d8..41d38cebdb 100644 --- a/src/versit/qvcard30writer.cpp +++ b/src/versit/qvcard30writer.cpp @@ -79,6 +79,7 @@ void QVCard30Writer::encodeVersitProperty(const QVersitProperty& property) writeString(QLatin1String(":")); QString renderedValue; + QByteArray renderedBytes; if (variant.canConvert<QVersitDocument>()) { QVersitDocument embeddedDocument = variant.value<QVersitDocument>(); QByteArray data; @@ -122,9 +123,16 @@ void QVCard30Writer::encodeVersitProperty(const QVersitProperty& property) } } } else if (variant.type() == QVariant::ByteArray) { - renderedValue = QLatin1String(variant.toByteArray().toBase64().data()); + if (mCodecIsAsciiCompatible) // optimize by not converting to unicode + renderedBytes = variant.toByteArray().toBase64(); + else + renderedValue = QLatin1String(variant.toByteArray().toBase64().data()); } - writeString(renderedValue); + + if (renderedBytes.isEmpty()) + writeString(renderedValue); + else + writeBytes(renderedBytes); writeCrlf(); } diff --git a/src/versit/qversitdocumentwriter_p.cpp b/src/versit/qversitdocumentwriter_p.cpp index 434b7052ef..21866049c7 100644 --- a/src/versit/qversitdocumentwriter_p.cpp +++ b/src/versit/qversitdocumentwriter_p.cpp @@ -93,6 +93,11 @@ void QVersitDocumentWriter::setCodec(QTextCodec *codec) // Hack so the encoder doesn't output a byte order mark for UTF-8. if (mCodec->name() == "UTF-8") mEncoder->fromUnicode(QString()); + + // UTF-(16|32)(LE|BE) are the only codecs where characters in the base64 range aren't encoded + // the same as in ASCII. For ASCII compatible codecs, we can do some optimizations. + mCodecIsAsciiCompatible = !(mCodec->name().startsWith("UTF-16") + || mCodec->name().startsWith("UTF-32")); } /*! @@ -175,6 +180,31 @@ void QVersitDocumentWriter::encodeGroupsAndName(const QVersitProperty& property) /*! Writes \a value to the device. + + This function tracks how many characters have been written to the line and folds (wraps) the line + according to RFC2425. + */ +void QVersitDocumentWriter::writeBytes(const QByteArray &value) +{ + int spaceRemaining = MAX_LINE_LENGTH - mCurrentLineLength; + int charsWritten = 0; + while (spaceRemaining < value.length() - charsWritten) { + // Write the first "spaceRemaining" characters + if (mDevice->write(value.mid(charsWritten, spaceRemaining)) < 0 + || mDevice->write("\r\n ") < 0) + mSuccessful = false; + charsWritten += spaceRemaining; + spaceRemaining = MAX_LINE_LENGTH - 1; // minus 1 for the space at the front. + mCurrentLineLength = 1; + } + + if (mDevice->write(value.mid(charsWritten)) < 0) + mSuccessful = false; + mCurrentLineLength += value.length() - charsWritten; +} + +/*! + Writes \a value to the device. If \a useUtf8 is true, uses the UTF-8 codec instead of the one set in setCodec(). This function tracks how many characters have been written to the line and folds (wraps) the line diff --git a/src/versit/qversitdocumentwriter_p.h b/src/versit/qversitdocumentwriter_p.h index 4c16acd242..ac43ec7242 100644 --- a/src/versit/qversitdocumentwriter_p.h +++ b/src/versit/qversitdocumentwriter_p.h @@ -87,6 +87,7 @@ protected: QVersitDocument::VersitType mType; QIODevice* mDevice; QTextCodec* mCodec; + bool mCodecIsAsciiCompatible; QTextEncoder* mEncoder; QTextEncoder* mUtf8Encoder; bool mSuccessful; |