diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-02-25 10:42:12 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-03-06 10:55:15 +0000 |
commit | a7b9a1f96658b92687bea02eac3615e5f3de4d7b (patch) | |
tree | beeaeffd9445341b9aa227b1c4cfa26bdd2032df /src/corelib/tools/qstring.cpp | |
parent | 80bfb8f1ad68c37260a295cd6df98acc571f4fde (diff) |
QString: make ucstrncmp() work for more than 2Gi characters
Required for implementing upcoming QStringView's member functions such
as compare(), indexOf(), endsWith(), ...
Most implementations of the function body just add the length to the
begin pointer to obtain an end pointer and then either no longer use
the length, or decrease it in lock-step with increasing the begin
pointer.
The only exception is MIPS DSP's qt_ucstrncmp_mips_dsp_asm(), which
gets the length passed in as an uint, implicitly converted from the
int parameter, proving that calling the function with negative length
was always undefined behavior, and therefore using an unsigned type
does not introduce incompatibilites.
I don't stand a snowball's chance in hell to fix the assembler
routine, but since the code is only included for MIPS32, we don't need
to do anything except be paranoid, add a static_assert that uint is
the same size as size_t, and keep calling the old code.
Dropped Q_COMPILER_LAMBDA in some places. We require lambdas since 5.7.
Also hold lambdas by value, not by reference. This stuff is supposedly
completely inlined, anyway, so there's no reason to make the code more
complicated with magic lifetime extension of temporaries bound to
references.
Change-Id: I0c7bdc47648b873992b51b2e9d47d808390320ea
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qstring.cpp')
-rw-r--r-- | src/corelib/tools/qstring.cpp | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 3c0ad1f3b5..13555042f8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -445,7 +445,7 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const ushort *a, #endif // Unicode case-sensitive compare two same-sized strings -static int ucstrncmp(const QChar *a, const QChar *b, int l) +static int ucstrncmp(const QChar *a, const QChar *b, size_t l) { #ifdef __OPTIMIZE_SIZE__ const QChar *end = a + l; @@ -458,6 +458,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) return 0; #else #if defined(__mips_dsp) + Q_STATIC_ASSERT(sizeof(uint) == sizeof(size_t)); if (l >= 8) { return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const ushort*>(a), reinterpret_cast<const ushort*>(b), @@ -484,13 +485,11 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) - reinterpret_cast<const QChar *>(ptr + distance + idx)->unicode(); } } -# if defined(Q_COMPILER_LAMBDA) - const auto &lambda = [=](int i) -> int { + const auto lambda = [=](size_t i) -> int { return reinterpret_cast<const QChar *>(ptr)[i].unicode() - reinterpret_cast<const QChar *>(ptr + distance)[i].unicode(); }; return UnrollTailLoop<7>::exec(l, 0, lambda, lambda); -# endif #endif #if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64 if (l >= 8) { @@ -511,7 +510,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) } l &= 7; } - const auto &lambda = [=](int i) -> int { + const auto lambda = [=](size_t i) -> int { return a[i].unicode() - b[i].unicode(); }; return UnrollTailLoop<7>::exec(l, 0, lambda, lambda); @@ -640,8 +639,8 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) uc += offset; c += offset; -# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__) - const auto &lambda = [=](int i) { return uc[i] - ushort(c[i]); }; +# if !defined(__OPTIMIZE_SIZE__) + const auto lambda = [=](size_t i) { return uc[i] - ushort(c[i]); }; return UnrollTailLoop<MaxTailLength>::exec(e - uc, 0, lambda, lambda); # endif #endif @@ -672,7 +671,7 @@ static int ucstrnicmp(const ushort *a, const ushort *b, int l) return ucstricmp(a, a + l, b, b + l); } -static bool qMemEquals(const quint16 *a, const quint16 *b, int length) +static bool qMemEquals(const quint16 *a, const quint16 *b, size_t length) { if (a == b || !length) return true; |