SVN commit 799413 by qbast: Ini parsing optimization - avoid using QByteArray and excessive memory copying. A bufferfragment_p.h [License: LGPL (v2+)] M +44 -48 kconfigini.cpp M +6 -1 kconfigini_p.h --- trunk/KDE/kdelibs/kdecore/config/kconfigini.cpp #799412:799413 @@ -29,6 +29,7 @@ #include "kconfig.h" #include "kconfigbackend.h" #include "kconfigini_p.h" +#include "bufferfragment_p.h" #include "kconfigdata.h" #include #include @@ -88,13 +89,17 @@ bool groupOptionImmutable = false; bool groupSkip = false; - int lineNo=0; + int lineNo = 0; // on systems using \r\n as end of line, \r will be taken care of by - // trimmed() below - QList lines=file.readAll().split('\n'); - for (int i=0;i= 0) { + while ((start = aKey.lastIndexOf('[')) >= 0) { int end = aKey.indexOf(']', start); if (end < 0) { qWarning() << warningProlog(file, lineNo) << "Invalid entry (missing ']')"; goto next_line; } else if (end > start + 1 && aKey.at(start + 1) == '$') { // found option(s) - int i = start+2; + int i = start + 2; while (i < end) { switch (aKey.at(i)) { case 'i': @@ -188,8 +197,9 @@ break; case 'd': entryOptions |= KEntryMap::EntryDeleted; - aKey = printableToString(aKey.left(start), file, lineNo); - entryMap.setEntry(currentGroup, aKey, QByteArray(), entryOptions); + aKey = aKey.left(start); + printableToString(&aKey, file, lineNo); + entryMap.setEntry(currentGroup, aKey.toByteArray(), QByteArray(), entryOptions); goto next_line; default: break; @@ -203,17 +213,16 @@ goto next_line; } - locale = aKey.mid(start+1,end-start-1); - rawKey = aKey.left(end+1); + locale = aKey.mid(start + 1,end - start - 1); + rawKey = aKey.left(end + 1); } - aKey.remove(start, end-start+1); + aKey.truncate(start); } - if (eqpos < 0) { // Do this here after [$d] was checked qWarning() << warningProlog(file, lineNo) << "Invalid entry (missing '=')"; continue; } - aKey = printableToString(aKey, file, lineNo); + printableToString(&aKey, file, lineNo); if (!locale.isEmpty()) { if (locale != currentLocale) { // backward compatibility. C == en_US @@ -221,12 +230,12 @@ if (merging){ entryOptions |= KEntryMap::EntryRawKey; aKey = rawKey; // store as unprocessed key - locale = QByteArray(); + locale = BufferFragment(); } else goto next_line; // skip this entry if we're not merging } } - } + } if (options&ParseGlobal) entryOptions |= KEntryMap::EntryGlobal; @@ -234,7 +243,8 @@ entryOptions |= KEntryMap::EntryDefault; if (!locale.isNull()) entryOptions |= KEntryMap::EntryLocalized; - entryMap.setEntry(currentGroup, aKey, printableToString(line, file, lineNo), entryOptions); + printableToString(&line, file, lineNo); + entryMap.setEntry(currentGroup, aKey.toByteArray(), line.toByteArray(), entryOptions); } next_line: continue; @@ -642,31 +652,18 @@ return char(ret); } -QByteArray KConfigIniBackend::printableToString(const QByteArray& aString, const QFile& file, int line) +void KConfigIniBackend::printableToString(BufferFragment* aString, const QFile& file, int line) { - if (aString.isEmpty()) - return QByteArray(""); + if (aString->isEmpty() || aString->indexOf('\\')==-1) + return; + aString->trim(); + int l = aString->length(); + char *r = aString->data(); + char *str=r; - const char *str = aString.constData(); - int l = aString.length(); - - // Strip leading white-space. - while((l > 0) && ((*str == ' ') || (*str == '\t') || (*str == '\r'))) { - str++; l--; - } - - - // Strip trailing white-space. - while((l > 0) && ((str[l-1] == ' ') || (str[l-1] == '\t') || (str[l-1] == '\r'))) { - l--; - } - - QByteArray result(l, 0); - char *r = result.data(); - for(int i = 0; i < l; i++, r++) { - if (str[i] != '\\') { - *r = str[i]; + if (str[i]!= '\\') { + *r=str[i]; } else { // Probable escape sequence i++; @@ -707,6 +704,5 @@ } } } - result.truncate(r - result.constData()); - return result; + aString->truncate(r - aString->constData()); } --- trunk/KDE/kdelibs/kdecore/config/kconfigini_p.h #799412:799413 @@ -29,6 +29,9 @@ class KConfigIniBackend : public KConfigBackend { +private: + class BufferFragment; + KLockFile::Ptr lockFile; public: @@ -61,7 +64,9 @@ KeyString = 1, ValueString = 2 }; - static QByteArray printableToString(const QByteArray& aString, const QFile& file, int line); + // Warning: this modifies data in-place. Other BufferFragment objects referencing the same buffer + // fragment will get their data modified too. + static void printableToString(BufferFragment* aString, const QFile& file, int line); static QByteArray stringToPrintable(const QByteArray& aString, StringType type); static char charFromHex(const char *str, const QFile& file, int line); static QString warningProlog(const QFile& file, int line);