Remove QLocalePrivate::m_localeID

It was only used for toUpper/toLower but always computed in the
constructor, including QString::toLatin1 conversion and allocations.

This needlessly slows down all other uses, including supposedly "cheap"
operations QString::toDouble, or accesses inside QResourceFileEngine.

The benchmarks indicates that doing it always when needed is bearable.
There's still a lot of improvement potential on these code paths.

Change-Id: I88b637ee11f9f7ea614f8da4ec5df0bf40664fce
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
bb10
hjk 2013-04-22 08:35:23 +02:00 committed by The Qt Project
parent adec3f4eaf
commit 01cbd7e4b5
5 changed files with 121 additions and 36 deletions

View File

@ -284,51 +284,51 @@ QLocaleId QLocaleId::withLikelySubtagsRemoved() const
return max;
}
QString QLocaleId::bcp47Name() const
QByteArray QLocaleId::name(char separator) const
{
if (language_id == QLocale::AnyLanguage)
return QString();
return QByteArray();
if (language_id == QLocale::C)
return QStringLiteral("C");
return QByteArrayLiteral("C");
const unsigned char *lang = language_code_list + 3*uint(language_id);
const unsigned char *lang = language_code_list + 3 * language_id;
const unsigned char *script =
(script_id != QLocale::AnyScript ? script_code_list + 4*uint(script_id) : 0);
(script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : 0);
const unsigned char *country =
(country_id != QLocale::AnyCountry ? country_code_list + 3*uint(country_id) : 0);
(country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : 0);
char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0);
QString name(len, Qt::Uninitialized);
QChar *uc = name.data();
*uc++ = ushort(lang[0]);
*uc++ = ushort(lang[1]);
QByteArray name(len, Qt::Uninitialized);
char *uc = name.data();
*uc++ = lang[0];
*uc++ = lang[1];
if (lang[2] != 0)
*uc++ = ushort(lang[2]);
*uc++ = lang[2];
if (script) {
*uc++ = QLatin1Char('-');
*uc++ = ushort(script[0]);
*uc++ = ushort(script[1]);
*uc++ = ushort(script[2]);
*uc++ = ushort(script[3]);
*uc++ = separator;
*uc++ = script[0];
*uc++ = script[1];
*uc++ = script[2];
*uc++ = script[3];
}
if (country) {
*uc++ = QLatin1Char('-');
*uc++ = ushort(country[0]);
*uc++ = ushort(country[1]);
*uc++ = separator;
*uc++ = country[0];
*uc++ = country[1];
if (country[2] != 0)
*uc++ = ushort(country[2]);
*uc++ = country[2];
}
return name;
}
QString QLocalePrivate::bcp47Name() const
QByteArray QLocalePrivate::bcp47Name(char separator) const
{
if (m_data->m_language_id == QLocale::AnyLanguage)
return QString();
return QByteArray();
if (m_data->m_language_id == QLocale::C)
return QStringLiteral("C");
return QByteArrayLiteral("C");
QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id, m_data->m_country_id);
return localeId.withLikelySubtagsRemoved().bcp47Name();
return localeId.withLikelySubtagsRemoved().name(separator);
}
const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country)
@ -1080,7 +1080,7 @@ QString QLocale::name() const
*/
QString QLocale::bcp47Name() const
{
return d->bcp47Name();
return QString::fromLatin1(d->bcp47Name());
}
/*!
@ -2494,7 +2494,7 @@ QString QLocale::toUpper(const QString &str) const
{
#ifdef QT_USE_ICU
bool ok = true;
QString result = QIcu::toUpper(d->m_localeID, str, &ok);
QString result = QIcu::toUpper(d->bcp47Name('_'), str, &ok);
if (ok)
return result;
// else fall through and use Qt's toUpper
@ -2511,7 +2511,7 @@ QString QLocale::toLower(const QString &str) const
{
#ifdef QT_USE_ICU
bool ok = true;
QString result = QIcu::toLower(d->m_localeID, str, &ok);
const QString result = QIcu::toLower(d->bcp47Name('_'), str, &ok);
if (ok)
return result;
// else fall through and use Qt's toUpper
@ -3662,14 +3662,14 @@ QStringList QLocale::uiLanguages() const
const QLocaleId min = max.withLikelySubtagsRemoved();
QStringList uiLanguages;
uiLanguages.append(min.bcp47Name());
uiLanguages.append(QString::fromLatin1(min.name()));
if (id.script_id) {
id.script_id = 0;
if (id != min && id.withLikelySubtagsAdded() == max)
uiLanguages.append(id.bcp47Name());
uiLanguages.append(QString::fromLatin1(id.name()));
}
if (max != min && max != id)
uiLanguages.append(max.bcp47Name());
uiLanguages.append(QString::fromLatin1(max.name()));
return uiLanguages;
}

View File

@ -151,7 +151,7 @@ struct QLocaleId
QLocaleId withLikelySubtagsAdded() const;
QLocaleId withLikelySubtagsRemoved() const;
QString bcp47Name() const;
QByteArray name(char separator = '-') const;
ushort language_id, script_id, country_id;
};
@ -212,8 +212,6 @@ public:
: m_index(index), m_numberOptions(numberOptions)
{
m_data = dataPointerForIndex(index);
m_localeID = bcp47Name().toLatin1();
m_localeID.replace('-','_');
}
~QLocalePrivate()
@ -232,7 +230,7 @@ public:
quint16 languageId() const { return m_data->m_language_id; }
quint16 countryId() const { return m_data->m_country_id; }
QString bcp47Name() const;
QByteArray bcp47Name(char separator = '-') const;
// ### QByteArray::fromRawData would be more optimal
inline QString languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
@ -334,11 +332,9 @@ public:
QString dateTimeToString(const QString &format, const QDate *date, const QTime *time,
const QLocale *q) const;
friend class QLocale;
quint16 m_index;
quint16 m_numberOptions;
const QLocaleData *m_data;
QByteArray m_localeID;
};
inline char QLocalePrivate::digitToCLocale(QChar in) const

View File

@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QLocale>
#include <QTest>
class tst_QLocale : public QObject
{
Q_OBJECT
private Q_SLOTS:
void toUpper_QLocale_1();
void toUpper_QLocale_2();
void toUpper_QString();
};
static QString data()
{
return QStringLiteral("/qt-5/qtbase/tests/benchmarks/corelib/tools/qlocale");
}
#define LOOP(s) for (int i = 0; i < 5000; ++i) { s; }
void tst_QLocale::toUpper_QLocale_1()
{
QString s = data();
QBENCHMARK { LOOP(QLocale().toUpper(s)) }
}
void tst_QLocale::toUpper_QLocale_2()
{
QString s = data();
QLocale l;
QBENCHMARK { LOOP(l.toUpper(s)) }
}
void tst_QLocale::toUpper_QString()
{
QString s = data();
QBENCHMARK { LOOP(s.toUpper()) }
}
QTEST_MAIN(tst_QLocale)
#include "main.moc"

View File

@ -0,0 +1,5 @@
TARGET = tst_bench_qlocale
QT = core testlib
SOURCES += main.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

View File

@ -5,6 +5,7 @@ SUBDIRS = \
qbytearray \
qcontiguouscache \
qlist \
qlocale \
qmap \
qrect \
qregexp \