summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2009-09-22 10:39:15 (GMT)
committerMarkus Goetz <Markus.Goetz@nokia.com>2009-11-11 10:38:33 (GMT)
commit0739771c29d38a4a2f2cb08560181195ad4e8e0c (patch)
treefc18d938ca1c180a51f25cc307924bfecb15bfd3 /src/network
parenta7dfc472b06966393a9d9c394d91ed8974b9cfb6 (diff)
downloadQt-0739771c29d38a4a2f2cb08560181195ad4e8e0c.zip
Qt-0739771c29d38a4a2f2cb08560181195ad4e8e0c.tar.gz
Qt-0739771c29d38a4a2f2cb08560181195ad4e8e0c.tar.bz2
QNAM: Parse RFC1123 directly and don't go through QLocale
The QDateTimeParser forces at least two QString allocations to convert the Month string into a integer. This makes parsing the date string the most expesnsive operation from within replyHeaderChanged. Use sscanf to parse the RFC1123 header to get a significant speedup. Use a switch case statement to convert the month name to a integer. Reviewed-By: Markus Goetz
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qnetworkrequest.cpp82
1 files changed, 74 insertions, 8 deletions
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 0e4326f..c91c608 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -804,6 +804,68 @@ void QNetworkHeadersPrivate::parseAndSetHeader(const QByteArray &key, const QByt
}
}
+// Fast month string to int conversion. This code
+// assumes that the Month name is correct and that
+// the string is at least three chars long.
+static int name_to_month(const char* month_str)
+{
+ switch (month_str[0]) {
+ case 'J':
+ switch (month_str[1]) {
+ case 'a':
+ return 1;
+ break;
+ case 'u':
+ switch (month_str[2] ) {
+ case 'n':
+ return 6;
+ break;
+ case 'l':
+ return 7;
+ break;
+ }
+ }
+ break;
+ case 'F':
+ return 2;
+ break;
+ case 'M':
+ switch (month_str[2] ) {
+ case 'r':
+ return 3;
+ break;
+ case 'y':
+ return 5;
+ break;
+ }
+ break;
+ case 'A':
+ switch (month_str[1]) {
+ case 'p':
+ return 4;
+ break;
+ case 'u':
+ return 8;
+ break;
+ }
+ break;
+ case 'O':
+ return 10;
+ break;
+ case 'S':
+ return 9;
+ break;
+ case 'N':
+ return 11;
+ break;
+ case 'D':
+ return 12;
+ break;
+ }
+
+ return 0;
+}
+
QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
{
// HTTP dates have three possible formats:
@@ -819,16 +881,20 @@ QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
// no comma -> asctime(3) format
dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
} else {
- // eat the weekday, the comma and the space following it
- QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
-
- QLocale c = QLocale::c();
- if (pos == 3)
- // must be RFC 1123 date
- dt = c.toDateTime(sansWeekday, QLatin1String("dd MMM yyyy hh:mm:ss 'GMT"));
- else
+ // Use sscanf over QLocal/QDateTimeParser for speed reasons. See the
+ // QtWebKit performance benchmarks to get an idea.
+ if (pos == 3) {
+ char month_name[4];
+ int day, year, hour, minute, second;
+ if (sscanf(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
+ dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
+ } else {
+ QLocale c = QLocale::c();
+ // eat the weekday, the comma and the space following it
+ QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
// must be RFC 850 date
dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
+ }
}
#endif // QT_NO_DATESTRING