diff options
Diffstat (limited to 'src/corelib/codecs')
-rw-r--r-- | src/corelib/codecs/codecs.pri | 23 | ||||
-rw-r--r-- | src/corelib/codecs/qicucodec.cpp | 10 | ||||
-rw-r--r-- | src/corelib/codecs/qtextcodec.cpp | 6 | ||||
-rw-r--r-- | src/corelib/codecs/qutfcodec.cpp | 87 | ||||
-rw-r--r-- | src/corelib/codecs/qwindowscodec.cpp | 2 |
5 files changed, 103 insertions, 25 deletions
diff --git a/src/corelib/codecs/codecs.pri b/src/corelib/codecs/codecs.pri index bfb677e6fb..fdaec33c5a 100644 --- a/src/corelib/codecs/codecs.pri +++ b/src/corelib/codecs/codecs.pri @@ -40,20 +40,17 @@ contains(QT_CONFIG,icu) { codecs/qeuckrcodec.cpp \ codecs/qbig5codec.cpp - unix:!qnx:!mac:!ios:!linux-android-* { - contains(QT_CONFIG,iconv) { - HEADERS += codecs/qiconvcodec_p.h - SOURCES += codecs/qiconvcodec.cpp - } else:contains(QT_CONFIG,gnu-libiconv) { - HEADERS += codecs/qiconvcodec_p.h - SOURCES += codecs/qiconvcodec.cpp - DEFINES += GNU_LIBICONV - LIBS_PRIVATE *= -liconv - } else:contains(QT_CONFIG,sun-libiconv) { - HEADERS += codecs/qiconvcodec_p.h - SOURCES += codecs/qiconvcodec.cpp - DEFINES += GNU_LIBICONV + unix:!qnx:!darwin:!linux-android-* { + contains(QT_CONFIG, iconv) { + HEADERS += codecs/qiconvcodec_p.h + SOURCES += codecs/qiconvcodec.cpp + contains(QT_CONFIG, gnu-libiconv) { + DEFINES += GNU_LIBICONV + LIBS_PRIVATE *= -liconv + } else: contains(QT_CONFIG, sun-libiconv) { + DEFINES += GNU_LIBICONV } + } } else:!win32-msvc* { DEFINES += QT_NO_ICONV } diff --git a/src/corelib/codecs/qicucodec.cpp b/src/corelib/codecs/qicucodec.cpp index aa2095d9da..ee9f1d0048 100644 --- a/src/corelib/codecs/qicucodec.cpp +++ b/src/corelib/codecs/qicucodec.cpp @@ -527,7 +527,7 @@ QTextCodec *QIcuCodec::codecForNameUnlocked(const char *name) // check whether there is really a converter for the name available. UConverter *conv = ucnv_open(standardName, &error); if (!conv) { - qDebug() << "codecForName: ucnv_open failed" << standardName << u_errorName(error); + qDebug("codecForName: ucnv_open failed %s %s", standardName, u_errorName(error)); return 0; } //qDebug() << "QIcuCodec: Standard name for " << name << "is" << standardName; @@ -577,7 +577,7 @@ UConverter *QIcuCodec::getConverter(QTextCodec::ConverterState *state) const ucnv_setSubstChars(static_cast<UConverter *>(state->d), state->flags & QTextCodec::ConvertInvalidToNull ? "\0" : "?", 1, &error); if (U_FAILURE(error)) - qDebug() << "getConverter(state) ucnv_open failed" << m_name << u_errorName(error); + qDebug("getConverter(state) ucnv_open failed %s %s", m_name, u_errorName(error)); } conv = static_cast<UConverter *>(state->d); } @@ -587,7 +587,7 @@ UConverter *QIcuCodec::getConverter(QTextCodec::ConverterState *state) const conv = ucnv_open(m_name, &error); ucnv_setSubstChars(conv, "?", 1, &error); if (U_FAILURE(error)) - qDebug() << "getConverter(no state) ucnv_open failed" << m_name << u_errorName(error); + qDebug("getConverter(no state) ucnv_open failed %s %s", m_name, u_errorName(error)); } return conv; } @@ -610,7 +610,7 @@ QString QIcuCodec::convertToUnicode(const char *chars, int length, QTextCodec::C &chars, end, 0, false, &error); if (!U_SUCCESS(error) && error != U_BUFFER_OVERFLOW_ERROR) { - qDebug() << "convertToUnicode failed:" << u_errorName(error); + qDebug("convertToUnicode failed: %s", u_errorName(error)); break; } @@ -647,7 +647,7 @@ QByteArray QIcuCodec::convertFromUnicode(const QChar *unicode, int length, QText &uc, end, 0, false, &error); if (!U_SUCCESS(error)) - qDebug() << "convertFromUnicode failed:" << u_errorName(error); + qDebug("convertFromUnicode failed: %s", u_errorName(error)); convertedChars = ch - string.data(); if (uc >= end) break; diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index edb03af447..5098ac4242 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -132,7 +132,7 @@ bool qTextCodecNameMatch(const char *n, const char *h) } -#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) && !defined(QT_LOCALE_IS_UTF8) +#if !defined(Q_OS_WIN32) && !defined(QT_LOCALE_IS_UTF8) static QTextCodec *checkForCodec(const QByteArray &name) { QTextCodec *c = QTextCodec::codecForName(name); if (!c) { @@ -169,7 +169,7 @@ static QTextCodec *setupLocaleMapper() #if defined(QT_LOCALE_IS_UTF8) locale = QTextCodec::codecForName("UTF-8"); -#elif defined(Q_OS_WIN) || defined(Q_OS_WINCE) +#elif defined(Q_OS_WIN) locale = QTextCodec::codecForName("System"); #else @@ -289,7 +289,7 @@ static void setup() #if !defined(QT_NO_ICONV) (void) new QIconvCodec; #endif -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#if defined(Q_OS_WIN32) (void) new QWindowsLocalCodec; #endif // Q_OS_WIN32 #endif // !QT_NO_CODECS && !QT_BOOTSTRAPPED diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index f1054ceb98..74a716db4a 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -52,6 +52,19 @@ enum { Endian = 0, Data = 1 }; static const uchar utf8bom[] = { 0xef, 0xbb, 0xbf }; +#if (defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)) \ + || (defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64)) +static Q_ALWAYS_INLINE uint qBitScanReverse(unsigned v) Q_DECL_NOTHROW +{ + uint result = qCountLeadingZeroBits(v); + // Now Invert the result: clz will count *down* from the msb to the lsb, so the msb index is 31 + // and the lsb index is 0. The result for _bit_scan_reverse is expected to be the index when + // counting up: msb index is 0 (because it starts there), and the lsb index is 31. + result ^= sizeof(unsigned) * 8 - 1; + return result; +} +#endif + #if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2) static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const ushort *&src, const ushort *end) { @@ -81,9 +94,9 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const // find the next probable ASCII character // we don't want to load 32 bytes again in this loop if we know there are non-ASCII // characters still coming - nextAscii = src + _bit_scan_reverse(n) + 1; + nextAscii = src + qBitScanReverse(n) + 1; - n = _bit_scan_forward(n); + n = qCountTrailingZeroBits(n); dst += n; src += n; return false; @@ -132,13 +145,81 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const // find the next probable ASCII character // we don't want to load 16 bytes again in this loop if we know there are non-ASCII // characters still coming - n = _bit_scan_reverse(n); + n = qBitScanReverse(n); nextAscii = src + (n / BitSpacing) + 1; return false; } return src == end; } +#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64 +static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const ushort *&src, const ushort *end) +{ + uint16x8_t maxAscii = vdupq_n_u16(0x7f); + uint16x8_t mask1 = { 1, 1 << 2, 1 << 4, 1 << 6, 1 << 8, 1 << 10, 1 << 12, 1 << 14 }; + uint16x8_t mask2 = vshlq_n_u16(mask1, 1); + + // do sixteen characters at a time + for ( ; end - src >= 16; src += 16, dst += 16) { + // load 2 lanes (or: "load interleaved") + uint16x8x2_t in = vld2q_u16(src); + + // check if any of the elements > 0x7f, select 1 bit per element (element 0 -> bit 0, element 1 -> bit 1, etc), + // add those together into a scalar, and merge the scalars. + uint16_t nonAscii = vaddvq_u16(vandq_u16(vcgtq_u16(in.val[0], maxAscii), mask1)) + | vaddvq_u16(vandq_u16(vcgtq_u16(in.val[1], maxAscii), mask2)); + + // merge the two lanes by shifting the values of the second by 8 and inserting them + uint16x8_t out = vsliq_n_u16(in.val[0], in.val[1], 8); + + // store, even if there are non-ASCII characters here + vst1q_u8(dst, vreinterpretq_u8_u16(out)); + + if (nonAscii) { + // find the next probable ASCII character + // we don't want to load 32 bytes again in this loop if we know there are non-ASCII + // characters still coming + nextAscii = src + qBitScanReverse(nonAscii) + 1; + + nonAscii = qCountTrailingZeroBits(nonAscii); + dst += nonAscii; + src += nonAscii; + return false; + } + } + return src == end; +} + +static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const uchar *&src, const uchar *end) +{ + // do eight characters at a time + uint8x8_t msb_mask = vdup_n_u8(0x80); + uint8x8_t add_mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 }; + for ( ; end - src >= 8; src += 8, dst += 8) { + uint8x8_t c = vld1_u8(src); + uint8_t n = vaddv_u8(vand_u8(vcge_u8(c, msb_mask), add_mask)); + if (!n) { + // store + vst1q_u16(dst, vmovl_u8(c)); + continue; + } + + // copy the front part that is still ASCII + while (!(n & 1)) { + *dst++ = *src++; + n >>= 1; + } + + // find the next probable ASCII character + // we don't want to load 16 bytes again in this loop if we know there are non-ASCII + // characters still coming + n = qBitScanReverse(n); + nextAscii = src + n + 1; + return false; + + } + return src == end; +} #else static inline bool simdEncodeAscii(uchar *, const ushort *, const ushort *, const ushort *) { diff --git a/src/corelib/codecs/qwindowscodec.cpp b/src/corelib/codecs/qwindowscodec.cpp index b802ab7249..813d3c8153 100644 --- a/src/corelib/codecs/qwindowscodec.cpp +++ b/src/corelib/codecs/qwindowscodec.cpp @@ -157,7 +157,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le state->remainingChars = 0; } const char *mb = mbcs; -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if !defined(Q_OS_WINRT) const char *next = 0; QString s; while ((next = CharNextExA(CP_ACP, mb, 0)) != mb) { |