Avoid using iconv for text conversion where possible
Try to use a builtin codec as codecForLocale() if possible first. Fall back and instantiate the iconv codec only if that failed. In addition, make sure we initialize the locale correctly before we try to setup the codec. Change-Id: I86d635f9d11e8ff93093f162e79fb37f3d85731b Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
1756a84756
commit
b25b3a9f8b
@ -88,8 +88,6 @@ static Ptr_iconv_close ptr_iconv_close = 0;
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
extern bool qt_locale_initialized;
|
|
||||||
|
|
||||||
QIconvCodec::QIconvCodec()
|
QIconvCodec::QIconvCodec()
|
||||||
: utf16Codec(0)
|
: utf16Codec(0)
|
||||||
{
|
{
|
||||||
@ -190,7 +188,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
QThreadStorage<QIconvCodec::IconvState *> *ts = toUnicodeState();
|
QThreadStorage<QIconvCodec::IconvState *> *ts = toUnicodeState();
|
||||||
if (!qt_locale_initialized || !ts) {
|
if (!ts) {
|
||||||
// we're running after the Q_GLOBAL_STATIC has been deleted
|
// we're running after the Q_GLOBAL_STATIC has been deleted
|
||||||
// or before the QCoreApplication initialization
|
// or before the QCoreApplication initialization
|
||||||
// bad programmer, no cookie for you
|
// bad programmer, no cookie for you
|
||||||
@ -346,7 +344,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
|
|||||||
|
|
||||||
IconvState *temporaryState = 0;
|
IconvState *temporaryState = 0;
|
||||||
QThreadStorage<QIconvCodec::IconvState *> *ts = fromUnicodeState();
|
QThreadStorage<QIconvCodec::IconvState *> *ts = fromUnicodeState();
|
||||||
IconvState *&state = (qt_locale_initialized && ts) ? ts->localData() : temporaryState;
|
IconvState *&state = ts ? ts->localData() : temporaryState;
|
||||||
if (!state) {
|
if (!state) {
|
||||||
iconv_t cd = QIconvCodec::createIconv_t(0, UTF16);
|
iconv_t cd = QIconvCodec::createIconv_t(0, UTF16);
|
||||||
if (cd != reinterpret_cast<iconv_t>(-1)) {
|
if (cd != reinterpret_cast<iconv_t>(-1)) {
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
#include "qfile.h"
|
#include "qfile.h"
|
||||||
#include "qstringlist.h"
|
#include "qstringlist.h"
|
||||||
#include "qvarlengtharray.h"
|
#include "qvarlengtharray.h"
|
||||||
|
#if !defined(QT_BOOTSTRAPPED)
|
||||||
|
#include <private/qcoreapplication_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
# include "qiconvcodec_p.h"
|
# include "qiconvcodec_p.h"
|
||||||
@ -82,8 +85,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && \
|
#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) && !defined(Q_OS_LINUX_ANDROID)
|
||||||
!defined(Q_OS_OSF) && !defined(Q_OS_LINUX_ANDROID)
|
|
||||||
# include <langinfo.h>
|
# include <langinfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -477,14 +479,11 @@ static bool try_locale_list(const char * const locale[], const QByteArray &lang)
|
|||||||
static const char * const probably_koi8_rlocales[] = {
|
static const char * const probably_koi8_rlocales[] = {
|
||||||
"ru", "ru_SU", "ru_RU", "russian", 0 };
|
"ru", "ru_SU", "ru_RU", "russian", 0 };
|
||||||
|
|
||||||
static QTextCodec * ru_RU_hack(const char * i) {
|
static QTextCodec * ru_RU_hack(const char * i)
|
||||||
|
{
|
||||||
QTextCodec * ru_RU_codec = 0;
|
QTextCodec * ru_RU_codec = 0;
|
||||||
|
|
||||||
#if !defined(QT_NO_SETLOCALE)
|
|
||||||
QByteArray origlocale(setlocale(LC_CTYPE, i));
|
QByteArray origlocale(setlocale(LC_CTYPE, i));
|
||||||
#else
|
|
||||||
QByteArray origlocale(i);
|
|
||||||
#endif
|
|
||||||
// unicode koi8r latin5 name
|
// unicode koi8r latin5 name
|
||||||
// 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU
|
// 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU
|
||||||
// 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU
|
// 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU
|
||||||
@ -500,16 +499,11 @@ static QTextCodec * ru_RU_hack(const char * i) {
|
|||||||
qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)",
|
qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)",
|
||||||
koi8r, latin5, i);
|
koi8r, latin5, i);
|
||||||
}
|
}
|
||||||
#if !defined(QT_NO_SETLOCALE)
|
|
||||||
setlocale(LC_CTYPE, origlocale.constData());
|
setlocale(LC_CTYPE, origlocale.constData());
|
||||||
#endif
|
|
||||||
|
|
||||||
return ru_RU_codec;
|
return ru_RU_codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)
|
|
||||||
static QTextCodec *checkForCodec(const QByteArray &name) {
|
static QTextCodec *checkForCodec(const QByteArray &name) {
|
||||||
QTextCodec *c = QTextCodec::codecForName(name);
|
QTextCodec *c = QTextCodec::codecForName(name);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
@ -531,16 +525,25 @@ static void setupLocaleMapper()
|
|||||||
localeMapper = QTextCodec::codecForName("System");
|
localeMapper = QTextCodec::codecForName("System");
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef QT_NO_ICONV
|
#if !defined(QT_BOOTSTRAPPED)
|
||||||
localeMapper = QTextCodec::codecForName("System");
|
QCoreApplicationPrivate::initLocale();
|
||||||
#endif
|
#endif
|
||||||
|
// First try getting the codecs name from nl_langinfo and see
|
||||||
|
// if we have a builtin codec for it.
|
||||||
|
// Only fall back to using iconv if we can't find a builtin codec
|
||||||
|
// This is because the builtin utf8 codec is around 5 times faster
|
||||||
|
// then the using QIconvCodec
|
||||||
|
|
||||||
#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && \
|
#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) && !defined(Q_OS_LINUX_ANDROID)
|
||||||
!defined(Q_OS_OSF) && !defined(Q_OS_LINUX_ANDROID)
|
char *charset = nl_langinfo(CODESET);
|
||||||
|
if (charset)
|
||||||
|
localeMapper = QTextCodec::codecForName(charset);
|
||||||
|
#endif
|
||||||
|
#if !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
|
||||||
if (!localeMapper) {
|
if (!localeMapper) {
|
||||||
char *charset = nl_langinfo (CODESET);
|
// no builtin codec for the locale found, let's try using iconv
|
||||||
if (charset)
|
(void) new QIconvCodec();
|
||||||
localeMapper = QTextCodec::codecForName(charset);
|
localeMapper = QTextCodec::codecForName("System");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -556,11 +559,7 @@ static void setupLocaleMapper()
|
|||||||
// First part is getting that locale name. First try setlocale() which
|
// First part is getting that locale name. First try setlocale() which
|
||||||
// definitely knows it, but since we cannot fully trust it, get ready
|
// definitely knows it, but since we cannot fully trust it, get ready
|
||||||
// to fall back to environment variables.
|
// to fall back to environment variables.
|
||||||
#if !defined(QT_NO_SETLOCALE)
|
|
||||||
const QByteArray ctype = setlocale(LC_CTYPE, 0);
|
const QByteArray ctype = setlocale(LC_CTYPE, 0);
|
||||||
#else
|
|
||||||
const QByteArray ctype;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
|
// Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
|
||||||
// environment variables.
|
// environment variables.
|
||||||
@ -723,13 +722,6 @@ static void setup()
|
|||||||
(void)new QLatin1Codec;
|
(void)new QLatin1Codec;
|
||||||
(void)new QUtf8Codec;
|
(void)new QUtf8Codec;
|
||||||
|
|
||||||
#if !defined(Q_OS_INTEGRITY)
|
|
||||||
#if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
|
|
||||||
// QIconvCodec depends on the UTF-16 codec, so it needs to be created last
|
|
||||||
(void) new QIconvCodec();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!localeMapper)
|
if (!localeMapper)
|
||||||
setupLocaleMapper();
|
setupLocaleMapper();
|
||||||
}
|
}
|
||||||
@ -1105,9 +1097,10 @@ void QTextCodec::setCodecForLocale(QTextCodec *c)
|
|||||||
Returns a pointer to the codec most suitable for this locale.
|
Returns a pointer to the codec most suitable for this locale.
|
||||||
|
|
||||||
On Windows, the codec will be based on a system locale. On Unix
|
On Windows, the codec will be based on a system locale. On Unix
|
||||||
systems, starting with Qt 4.2, the codec will be using the \e
|
systems, the codec will might fall back to using the \e iconv
|
||||||
iconv library. Note that in both cases the codec's name will be
|
library if no builtin codec for the locale can be found.
|
||||||
"System".
|
|
||||||
|
Note that in these cases the codec's name will be "System".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QTextCodec* QTextCodec::codecForLocale()
|
QTextCodec* QTextCodec::codecForLocale()
|
||||||
|
@ -230,7 +230,7 @@ bool QCoreApplicationPrivate::is_app_running = false;
|
|||||||
// app closing down if true
|
// app closing down if true
|
||||||
bool QCoreApplicationPrivate::is_app_closing = false;
|
bool QCoreApplicationPrivate::is_app_closing = false;
|
||||||
// initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
|
// initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
|
||||||
Q_CORE_EXPORT bool qt_locale_initialized = false;
|
static bool qt_locale_initialized = false;
|
||||||
|
|
||||||
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
|
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
|
||||||
{
|
{
|
||||||
@ -405,6 +405,17 @@ QString qAppName()
|
|||||||
return QCoreApplication::instance()->d_func()->appName();
|
return QCoreApplication::instance()->d_func()->appName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCoreApplicationPrivate::initLocale()
|
||||||
|
{
|
||||||
|
if (qt_locale_initialized)
|
||||||
|
return;
|
||||||
|
qt_locale_initialized = true;
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QCoreApplication
|
\class QCoreApplication
|
||||||
\brief The QCoreApplication class provides an event loop for console Qt
|
\brief The QCoreApplication class provides an event loop for console Qt
|
||||||
@ -543,10 +554,7 @@ void QCoreApplication::init()
|
|||||||
{
|
{
|
||||||
Q_D(QCoreApplication);
|
Q_D(QCoreApplication);
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
QCoreApplicationPrivate::initLocale();
|
||||||
setlocale(LC_ALL, ""); // use correct char set mapping
|
|
||||||
qt_locale_initialized = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
|
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
|
||||||
QCoreApplication::self = this;
|
QCoreApplication::self = this;
|
||||||
|
@ -89,6 +89,8 @@ public:
|
|||||||
static QString macMenuBarName();
|
static QString macMenuBarName();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void initLocale();
|
||||||
|
|
||||||
QAtomicInt quitLockRef;
|
QAtomicInt quitLockRef;
|
||||||
void ref();
|
void ref();
|
||||||
void deref();
|
void deref();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user