[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: branches/KDE/4.3/kdelibs/kdecore/localization
From: Chusslove Illich <caslav.ilic () gmx ! net>
Date: 2009-10-10 21:01:53
Message-ID: 1255208513.754966.21672.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 1033708 by ilic:
New version of compiled pmaps, with loading time O(entries) rather than \
O(entries*properties). (bport: 1033706)
M +144 -19 ktranscript.cpp
--- branches/KDE/4.3/kdelibs/kdecore/localization/ktranscript.cpp #1033707:1033708
@@ -38,6 +38,8 @@
#include <QStringList>
#include <QList>
#include <QHash>
+#include <QPair>
+#include <QSet>
#include <QFile>
#include <QIODevice>
#include <QTextStream>
@@ -156,8 +158,10 @@
};
// Helper methods to interface functions.
+ QString loadProps_text (const QString &fpath);
QString loadProps_bin (const QString &fpath);
- QString loadProps_text (const QString &fpath);
+ QString loadProps_bin_00 (const QString &fpath);
+ QString loadProps_bin_01 (const QString &fpath);
// Virtual implementations.
bool getOwnPropertySlot (ExecState *exec, const Identifier& propertyName, \
PropertySlot& slot); @@ -197,6 +201,13 @@
// Not QStrings, in order to avoid conversion from UTF-8 when
// loading compiled maps (less latency on startup).
QHash<QByteArray, QHash<QByteArray, QByteArray> > phraseProps;
+ // Unresolved property values per phrase,
+ // containing the pointer to compiled pmap file handle and offset in it.
+ QHash<QByteArray, QPair<QFile*, quint64> > phraseUnparsedProps;
+ QHash<QByteArray, QByteArray> resolveUnparsedProps (const QByteArray &phrase);
+ // Set of loaded pmap files by paths and file handle pointers.
+ QSet<QString> loadedPmapPaths;
+ QSet<QFile*> loadedPmapHandles;
// User config.
TsConfigGroup config;
@@ -729,7 +740,9 @@
{}
Scriptface::~Scriptface ()
-{}
+{
+ qDeleteAll(loadedPmapHandles);
+}
bool Scriptface::getOwnPropertySlot (ExecState *exec, const Identifier& \
propertyName, PropertySlot& slot) {
@@ -1061,7 +1074,7 @@
JSValue *Scriptface::msgkeyf (ExecState *exec)
{
Q_UNUSED(exec);
- return jsString(*msgctxt + '|' + *msgid);
+ return jsString(QString(*msgctxt + '|' + *msgid));
}
JSValue *Scriptface::msgstrff (ExecState *exec)
@@ -1143,17 +1156,20 @@
file_check.close();
// Load from appropriate type of map.
- QString errorString;
- if (haveCompiled) {
- errorString = loadProps_bin(qfpath);
+ if (!loadedPmapPaths.contains(qfpath)) {
+ QString errorString;
+ if (haveCompiled) {
+ errorString = loadProps_bin(qfpath);
+ }
+ else {
+ errorString = loadProps_text(qfpath);
+ }
+ if (!errorString.isEmpty()) {
+ return throwError(exec, SyntaxError, errorString);
+ }
+ dbgout("Loaded property map: %1", qfpath);
+ loadedPmapPaths.insert(qfpath);
}
- else {
- errorString = loadProps_text(qfpath);
- }
- if (!errorString.isEmpty()) {
- return throwError(exec, SyntaxError, errorString);
- }
- dbgout("Loaded property map: %1", qfpath);
}
return jsUndefined();
@@ -1172,6 +1188,9 @@
QByteArray qphrase = normKeystr(phrase->toString(exec).qstring());
QHash<QByteArray, QByteArray> props = phraseProps.value(qphrase);
+ if (props.isEmpty()) {
+ props = resolveUnparsedProps(qphrase);
+ }
if (!props.isEmpty()) {
QByteArray qprop = normKeystr(prop->toString(exec).qstring());
QByteArray qval = props.value(qprop);
@@ -1543,19 +1562,38 @@
return QString();
}
-static int bin_read_int (const char *fc, qlonglong len, qlonglong &pos)
+// Read big-endian integer of nbytes length at position pos
+// in character array fc of length len.
+// Update position to point after the number.
+// In case of error, pos is set to -1.
+template <typename T>
+static int bin_read_int_nbytes (const char *fc, qlonglong len, qlonglong &pos, int \
nbytes) {
- // Binary format is big-endian, 32-bit integer.
- static const int nbytes = 4;
if (pos + nbytes > len) {
pos = -1;
return 0;
}
- int num = qFromBigEndian<quint32>((uchar*) fc + pos);
+ T num = qFromBigEndian<T>((uchar*) fc + pos);
pos += nbytes;
return num;
}
+// Read 64-bit big-endian integer.
+static quint64 bin_read_int64 (const char *fc, qlonglong len, qlonglong &pos)
+{
+ return bin_read_int_nbytes<quint64>(fc, len, pos, 8);
+}
+
+// Read 32-bit big-endian integer.
+static quint32 bin_read_int (const char *fc, qlonglong len, qlonglong &pos)
+{
+ return bin_read_int_nbytes<quint32>(fc, len, pos, 4);
+}
+
+// Read string at position pos of character array fc of lenght n.
+// String is represented as 32-bit big-endian byte length followed by bytes.
+// Update position to point after the string.
+// In case of error, pos is set to -1.
static QByteArray bin_read_string (const char *fc, qlonglong len, qlonglong &pos)
{
// Binary format stores strings as length followed by byte sequence.
@@ -1577,9 +1615,33 @@
{
QFile file(fpath);
if (!file.open(QIODevice::ReadOnly)) {
- return QString(SPREF"loadProps_bin: cannot read file '%1'")
+ return QString(SPREF"loadProps: cannot read file '%1'")
.arg(fpath);
}
+ // Collect header.
+ QByteArray head(8, '0');
+ file.read(head.data(), head.size());
+ file.close();
+
+ // Choose pmap loader based on header.
+ if (head == "TSPMAP00") {
+ return loadProps_bin_00(fpath);
+ } else if (head == "TSPMAP01") {
+ return loadProps_bin_01(fpath);
+ }
+ else {
+ return QString(SPREF"loadProps: unknown version of compiled map '%1'")
+ .arg(fpath);
+ }
+}
+
+QString Scriptface::loadProps_bin_00 (const QString &fpath)
+{
+ QFile file(fpath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ return QString(SPREF"loadProps: cannot read file '%1'")
+ .arg(fpath);
+ }
QByteArray fctmp = file.readAll();
file.close();
const char *fc = fctmp.data();
@@ -1634,9 +1696,72 @@
END_PROP_PARSE:
if (pos < 0) {
- return QString(SPREF"loadProps_bin: corrupt compiled map %1")
+ return QString(SPREF"loadProps: corrupt compiled map '%1'")
.arg(fpath);
}
return QString();
}
+
+QString Scriptface::loadProps_bin_01 (const QString &fpath)
+{
+ QFile *file = new QFile(fpath);
+ if (!file->open(QIODevice::ReadOnly)) {
+ return QString(SPREF"loadProps: cannot read file '%1'")
+ .arg(fpath);
+ }
+
+ QByteArray fstr;
+ qlonglong pos;
+
+ // Read the header and number and length of entry keys.
+ fstr = file->read(8 + 4 + 8);
+ pos = 0;
+ QByteArray head = fstr.left(8);
+ pos += 8;
+ if (head != "TSPMAP01") {
+ return QString(SPREF"loadProps: corrupt compiled map '%1'")
+ .arg(fpath);
+ }
+ quint32 numekeys = bin_read_int(fstr, fstr.size(), pos);
+ quint64 lenekeys = bin_read_int64(fstr, fstr.size(), pos);
+
+ // Read entry keys.
+ fstr = file->read(lenekeys);
+ pos = 0;
+ for (quint32 i = 0; i < numekeys; ++i) {
+ QByteArray ekey = bin_read_string(fstr, lenekeys, pos);
+ quint64 offset = bin_read_int64(fstr, lenekeys, pos);
+ phraseUnparsedProps[ekey] = QPair<QFile*, quint64>(file, offset);
+ }
+
+ // // Read property keys.
+ // ...when it becomes necessary
+
+ loadedPmapHandles.insert(file);
+ return QString();
+}
+
+QHash<QByteArray, QByteArray> Scriptface::resolveUnparsedProps (const QByteArray \
&phrase) +{
+ QPair<QFile*, quint64> ref = phraseUnparsedProps.value(phrase);
+ QFile *file = ref.first;
+ quint64 offset = ref.second;
+ QHash<QByteArray, QByteArray> props;
+ if (file != NULL && file->seek(offset)) {
+ QByteArray fstr = file->read(4 + 4);
+ qlonglong pos = 0;
+ quint32 numpkeys = bin_read_int(fstr, fstr.size(), pos);
+ quint32 lenpkeys = bin_read_int(fstr, fstr.size(), pos);
+ fstr = file->read(lenpkeys);
+ pos = 0;
+ for (quint32 i = 0; i < numpkeys; ++i) {
+ QByteArray pkey = bin_read_string(fstr, lenpkeys, pos);
+ QByteArray pval = bin_read_string(fstr, lenpkeys, pos);
+ props[pkey] = pval;
+ }
+ phraseProps[phrase] = props;
+ phraseUnparsedProps.remove(phrase);
+ }
+ return props;
+}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic