summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Wu Won <kevin.wu-won@nokia.com>2010-10-12 14:52:31 +1000
committerKevin Wu Won <kevin.wu-won@nokia.com>2010-10-12 15:24:00 +1000
commitce598790f41edfcb8439833ddf6f4967996ee576 (patch)
tree74b722c1926726402824a886053f8a8519288ea3
parent72e8ff3f6579e661443c33a882a138384df46a04 (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.cpp11
-rw-r--r--src/versit/qvcard30writer.cpp12
-rw-r--r--src/versit/qversitdocumentwriter_p.cpp30
-rw-r--r--src/versit/qversitdocumentwriter_p.h1
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;