diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2020-04-24 12:54:20 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2020-05-09 06:25:05 +0000 |
commit | 19e7c0d2b5a807e194be1d65b16041f48136c9be (patch) | |
tree | 4d6df4cf5e84e4fc6bcad63c4aa07222fc0c36bc /src/corelib/text/qchar.cpp | |
parent | f6b96bc34749e4478e75c081bbd0af406cd737b5 (diff) |
QChar/QString: centralize case folding in qchar.cpp
There are (at least) two implementations of the low-level case-folding
algorithm, one of which (for QChar::toLower()) seems to be wrong (it
doesn't deal with special cases which expand to more than one code
point).
The algoithm hidden in QString and entangled with the QString
detaching code makes reusing the code much harder.
At the same time, the dependency of the algorithm on the unicode
tables makes exposing a non-allocating result type in the public API
hard. std::u16string would be an alternative if we can assure that all
implementations use SSO with at least four characters.
So, for the time being, leave this as internal API for use in an
upcoming QStringView::toLower() as well as case-insensitive hashing.
Change-Id: Iabb2611846f6176776aa20e634f44d8464f3305c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/text/qchar.cpp')
-rw-r--r-- | src/corelib/text/qchar.cpp | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp index 6b1bb33949..1b8cfb642e 100644 --- a/src/corelib/text/qchar.cpp +++ b/src/corelib/text/qchar.cpp @@ -1550,6 +1550,29 @@ QChar::UnicodeVersion QChar::currentUnicodeVersion() noexcept return UNICODE_DATA_VERSION; } +using FullConvertCaseResult = std::array<char16_t, MaxSpecialCaseLength + 1>; +static FullConvertCaseResult fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept +{ + FullConvertCaseResult result = {}; + auto pp = result.begin(); + + const auto fold = qGetProp(uc)->cases[which]; + const auto caseDiff = fold.diff; + + if (Q_UNLIKELY(fold.special)) { + const auto *specialCase = specialCaseMap + caseDiff; + auto length = *specialCase++; + while (length--) + *pp++ = *specialCase++; + } else if (Q_UNLIKELY(QChar::requiresSurrogates(uc))) { + // so far, case convertion never changes planes (guaranteed by the qunicodetables generator) + *pp++ = QChar::highSurrogate(uc); + *pp++ = QChar::lowSurrogate(uc + caseDiff); + } else { + *pp++ = uc + caseDiff; + } + return result; +} template <typename T> Q_DECL_CONST_FUNCTION static inline T convertCase_helper(T uc, QUnicodeTables::Case which) noexcept |