From 829d85a70ace8c482a2f191f6697700cced68da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 21 Dec 2023 01:31:44 +0100 Subject: [PATCH] Optimize TextCodec initialization QTextCodec initialization is very slow due to it's broken caching in Qt when ICU is enabled. Make TetCodec initialize fast anyway as it may be used very often in IMG maps (every LBL subfile has it's own codec!). --- src/common/textcodec.cpp | 82 ++++++++++++++++++--------------------- src/common/textcodec.h | 5 ++- src/data/gpiparser.cpp | 2 +- src/data/twonavparser.cpp | 2 +- src/map/IMG/lblfile.h | 10 ++--- 5 files changed, 48 insertions(+), 53 deletions(-) diff --git a/src/common/textcodec.cpp b/src/common/textcodec.cpp index dc0865a1..28db0683 100644 --- a/src/common/textcodec.cpp +++ b/src/common/textcodec.cpp @@ -1,56 +1,48 @@ #include #include "textcodec.h" -TextCodec::TextCodec() +/* When Qt is compiled with ICU support, QTextCodec::codecForName() is very + slow due to broken codec name caching (the function does dozens of + comparisons and only then asks the cache...), so we use our own map. */ +static QMap initCodecs() { - _codec = QTextCodec::codecForName("Windows-1252"); + QMap map; + + map.insert(65001, 0); + map.insert(874, QTextCodec::codecForName("Windows-874")); + map.insert(932, QTextCodec::codecForName("Shift-JIS")); + map.insert(936, QTextCodec::codecForName("GB18030")); + map.insert(949, QTextCodec::codecForName("EUC-KR")); + map.insert(950, QTextCodec::codecForName("Big5")); + map.insert(1250, QTextCodec::codecForName("Windows-1250")); + map.insert(1251, QTextCodec::codecForName("Windows-1251")); + map.insert(1252, QTextCodec::codecForName("Windows-1252")); + map.insert(1253, QTextCodec::codecForName("Windows-1253")); + map.insert(1254, QTextCodec::codecForName("Windows-1254")); + map.insert(1255, QTextCodec::codecForName("Windows-1255")); + map.insert(1256, QTextCodec::codecForName("Windows-1256")); + map.insert(1257, QTextCodec::codecForName("Windows-1257")); + map.insert(1258, QTextCodec::codecForName("Windows-1258")); + + return map; +} + +const QMap &TextCodec::codecs() +{ + static QMap map = initCodecs(); + return map; } TextCodec::TextCodec(int codepage) { - switch (codepage) { - case 65001: - _codec = 0; - break; - case 932: - _codec = QTextCodec::codecForName("Shift-JIS"); - break; - case 936: - _codec = QTextCodec::codecForName("GB18030"); - break; - case 949: - _codec = QTextCodec::codecForName("EUC-KR"); - break; - case 950: - _codec = QTextCodec::codecForName("Big5"); - break; - case 1250: - _codec = QTextCodec::codecForName("Windows-1250"); - break; - case 1251: - _codec = QTextCodec::codecForName("Windows-1251"); - break; - case 1253: - _codec = QTextCodec::codecForName("Windows-1253"); - break; - case 1254: - _codec = QTextCodec::codecForName("Windows-1254"); - break; - case 1255: - _codec = QTextCodec::codecForName("Windows-1255"); - break; - case 1256: - _codec = QTextCodec::codecForName("Windows-1256"); - break; - case 1257: - _codec = QTextCodec::codecForName("Windows-1257"); - break; - case 1258: - _codec = QTextCodec::codecForName("Windows-1258"); - break; - default: - _codec = QTextCodec::codecForName("Windows-1252"); - } + const QMap &map = codecs(); + + QMap::const_iterator it(map.find(codepage)); + if (it == map.cend()) { + qWarning("%d: Unsupported codepage, using UTF-8", codepage); + _codec = 0; + } else + _codec = *it; } QString TextCodec::toString(const QByteArray &ba) const diff --git a/src/common/textcodec.h b/src/common/textcodec.h index c014d9c1..a5279ce7 100644 --- a/src/common/textcodec.h +++ b/src/common/textcodec.h @@ -2,19 +2,22 @@ #define TEXTCODEC_H #include +#include class QTextCodec; class TextCodec { public: - TextCodec(); + TextCodec() : _codec(0) {} TextCodec(int codepage); QString toString(const QByteArray &ba) const; private: QTextCodec *_codec; + + static const QMap &codecs(); }; #endif // TEXTCODEC_H diff --git a/src/data/gpiparser.cpp b/src/data/gpiparser.cpp index 47c2ea91..6755abae 100644 --- a/src/data/gpiparser.cpp +++ b/src/data/gpiparser.cpp @@ -128,7 +128,7 @@ qint64 CryptDevice::readData(char *data, qint64 maxSize) class DataStream : public QDataStream { public: - DataStream(QIODevice *d) : QDataStream(d) {} + DataStream(QIODevice *d) : QDataStream(d), _codec(1252) {} void setCodepage(quint16 codepage) {_codec = TextCodec(codepage);} diff --git a/src/data/twonavparser.cpp b/src/data/twonavparser.cpp index 76c91c0d..57206176 100644 --- a/src/data/twonavparser.cpp +++ b/src/data/twonavparser.cpp @@ -75,7 +75,7 @@ bool TwoNavParser::parse(QFile *file, QList &tracks, QVector &waypoints) { Q_UNUSED(polygons); - TextCodec codec; + TextCodec codec(1252); GCS gcs; bool ok, route = false, track = false, waypoint = false; diff --git a/src/map/IMG/lblfile.h b/src/map/IMG/lblfile.h index e3a01201..3a361b97 100644 --- a/src/map/IMG/lblfile.h +++ b/src/map/IMG/lblfile.h @@ -16,14 +16,14 @@ class LBLFile : public SubFile { public: LBLFile(const IMGData *img) - : SubFile(img), _huffmanText(0), _table(0), _rasters(0), _imgIdSize(0), - _poiShift(0), _shift(0), _encoding(0) {} + : SubFile(img), _huffmanText(0), _table(0), _rasters(0), _codec(1252), + _imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {} LBLFile(const QString *path) - : SubFile(path), _huffmanText(0), _table(0), _rasters(0), _imgIdSize(0), - _poiShift(0), _shift(0), _encoding(0) {} + : SubFile(path), _huffmanText(0), _table(0), _rasters(0), _codec(1252), + _imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {} LBLFile(const SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _huffmanText(0), _table(0), _rasters(0), - _imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {} + _codec(1252), _imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {} ~LBLFile(); bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);