summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
Commit message (Collapse)AuthorAgeFilesLines
* Replace cxx17_bm_searcher config check with feature test macroMarc Mutz2022-01-241-1/+1
| | | | | | | | | | This enables the code also for boostrap. Amends b24e689cb561d81745ff47a5ce4595b809923914. Pick-to: 6.3 Change-Id: I8efc76c20690282a2428f360d6b93896966b97ee Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Optimize finding UTF-16 needles in L1 haystacksMarc Mutz2022-01-241-3/+6
| | | | | | | | | | | | We were converting the full L1 haystack to UTF-16. But, even so, we won't be able to find non-L1 UTF-16 needles in L1 haystacks! Optimize by converting the needle (not the haystack) to L1, after checking it's actually L1. Pick-to: 6.3 Change-Id: I413d7a602d44ecb2d3149dc4fa87c690c40e6aaa Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QStaticByteArrayMatcherBase: make dtor protectedMarc Mutz2022-01-231-1/+1
| | | | | | | | | | | Base class dtors should either be public and virtual or else protected and non-virtual. We don't want to model polymorphy, so protected and non-virtual it is. Pick-to: 6.3 Change-Id: I3c545b01c3ec831ee8b4a0c522501222a69923e9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Q(Static)ByteArrayMatcher: manage indexIn() overloadsMarc Mutz2022-01-232-19/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Unlike QString and QStringView, QByteArrayView and QByteArray don't overload well. Solve the overload issue the usual way: by making the QByteArray one a Q_WEAK_OVERLOAD. This is trivial for QStaticByteArrayMatcher, which isn't exported, but require QT_REMOVED_SINCE magic for QByteArrayMatcher, which is. The additional const char* overload has shielded us from the worst fall-out so far, it seems, but it makes for a truly horrible overload set: matcher.indexIn(str, 3); Q: Is the 3 here the length of the haystack or the value of the from parameter? A: It depends on decltype(str)! If the (const char*, qsizetype, qsizetype=0) overload is the better match, then 3 limits the haystack's length. If, otoh, the (QByteArray(View), qsizetype) overload is the better match, then it's the value of the from parameter. As if this wasn't bad enough, QByteArray implcitly converts to const char* by default! A follow-up patch will therefore deprecate the (ptr, size) overloads, so we de-inline the QByteArrayView ones to avoid having to touch the implementation once more. Found during 6.3 API review. Pick-to: 6.3 Change-Id: I9640e0bdd298d651511adebcc85f314db9221d34 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QStaticByteArrayMatcher: fix searching in 2+GiB haystacksMarc Mutz2022-01-232-14/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add a test (same techniques as for the 4+GiB check in tst_qcryptographichash). Takes ~1s to build the 4GiB test data here, and skips when RAM is too low: $ qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher haystacksWithMoreThan4GiBWork [...] QDEBUG : tst_QByteArrayMatcher::haystacksWithMoreThan4GiBWork() created dataset in 891 ms [...] $ (ulimit -v 2000000; qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher haystacksWithMoreThan4GiBWork) ********* Start testing of tst_QByteArrayMatcher ********* [...] SKIP : tst_QByteArrayMatcher::haystacksWithMoreThan4GiBWork() Could not allocate 4GiB plus a couple hundred bytes of RAM. Loc: [/home/marc/Qt/qt5/qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp(242)] [...] Found during 6.3 API review. [ChangeLog][QtCore][QStaticByteArrayMatcher] Fixed searching in strings with size > 2GiB (on 64-bit platforms). Fixes: QTBUG-100118 Pick-to: 6.3 Change-Id: I1df420965673b5555fef2b75e785954cc50b654f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QByteArrayList: optimize 32-bit builds of legacy join() helperMarc Mutz2022-01-222-6/+6
| | | | | | | | | | | | | | On 32-bit machines, qsizetype is int, so we don't actually need to QT_REMOVE_SINCE the QByteArrayList_join() helper, because it didn't change. Thanks to Thiago for showing me the QT_POINTER_SIZE trick in a similar change to QVersionNumber. Pick-to: 6.3 Change-Id: Iae6e315107e42da51fcb4e7325b6d40b9c3fe0bc Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QByteArrayList: micro-optimize join(QByteArray)Marc Mutz2022-01-221-1/+1
| | | | | | | | | | | | Null- vs. emptiness of the separator is not significant for join(), so skip the isNull() check in the conversion ctor of QByteArrayView from QByteArray by using the named conversion function that exists for this purpose instead. Pick-to: 6.3 Change-Id: I6ef07cc9bcc0bc8b87ecadc5cfaac9793cfb1b77 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QByteArrayList: simplify the join() overload set already nowMarc Mutz2022-01-222-10/+2
| | | | | | | | | | | | | | | | ... instead of waiting for Qt 7. Found in API review. [ChangeLog][QtCore][Potentially Source-Incompatible Changes] [QByteArrayList] The join() overload set has changed. Code such as qOverload<>(&QByteArrayList::join) will have to be rewritten, e.g. using lambdas. We advise against taking addresses of library functions other than signals and slots. Pick-to: 6.3 Change-Id: I67449df9adc2efea7f1163034caa135f31f39e7c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* [doc] QStaticByteArrayMatcher: remove references to C++ < 17Marc Mutz2022-01-211-7/+1
| | | | | | | | | This class is universally supported by all Qt6-capable compilers. Pick-to: 6.3 6.2 Change-Id: Ib03ed8f73fe656e47f4d0f8f50c3a8ff95b6d8d4 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QStaticByteArrayMatcher: add a useful commentMarc Mutz2022-01-211-0/+1
| | | | | | | | | Took me a few seconds to figure this out, and I'm the author of the class, so leave a comment for my future self (and anyone else). Pick-to: 6.3 6.2 5.15 Change-Id: I65a7aa6f8abf9d671f7d9ba45400f19e0f46728f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QStringConverter: use QStaticByteArrayMatcherMarc Mutz2022-01-211-2/+5
| | | | | | | | | | | | The Boyer-Moore tables can be calculated at compile-time, and the needles are long enough to make skipping worthwhile, even for small haystacks. Pick-to: 6.3 Change-Id: I3237812490367ed0491eb8d1667c6da67f38c517 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QByteArrayMatcher users: use the new QByteArrayView overloadsMarc Mutz2022-01-212-4/+4
| | | | | | | | | | The new overloads mean that when passing QByteArrayView or QLatin1String objects, we don't expand them into .data() and .size() anymore. Pick-to: 6.3 Change-Id: I0c898e0463d0bf81ce1f7d57e10e64f23bd84587 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
* QStringConverter: fix int/qsizetype mismatches (ex Win32)Marc Mutz2022-01-211-9/+9
| | | | | | | | I can't test on Windows, so skipped the platform-specific code. Pick-to: 6.3 6.2 Change-Id: Id13d4abc447ddd5d17fb67b670b83207877456f6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QtCore: replace qSwap with std::swap/member-swap where possibleMarc Mutz2022-01-204-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | qSwap() is a monster that looks for ADL overloads of swap() and also detects the noexcept of the wrapped swap() function, so it should only be used when the argument type is unknown. In the vast majority of cases, the type is known to be efficiently std::swap()able or to have a member-swap. Call either of these. For the common case of pointer types, circumvent the expensive trait checks on std::swap() by providing a hand-rolled qt_ptr_swap() template, the advantage being that it can be unconditionally noexcept, removing all type traits instantiations. Don't document it, otherwise we'd be unable to pick it to 6.2. Effects on Clang -ftime-trace of a PCH'ed libQt6Gui.so build: before: **** Template sets that took longest to instantiate: [...] 27766 ms: qSwap<$> (9073 times, avg 3 ms) [...] 2806 ms: std::swap<$> (1229 times, avg 2 ms) (30572ms) after: **** Template sets that took longest to instantiate: [...] 5047 ms: qSwap<$> (641 times, avg 7 ms) [...] 3371 ms: std::swap<$> (1376 times, avg 2 ms) [qt_ptr_swap<$> does not appear in the top 400, so < 905ms] (< 9323ms) As a drive-by, remove superfluous inline keywords and template ornaments. Task-number: QTBUG-97601 Pick-to: 6.3 6.2 Change-Id: I88f9b4e3cbece268c4a1238b6d50e5712a1bab5a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Doc: Cross-link QString's methodsIvan Tkachenko2022-01-191-3/+5
| | | | | | | | | | Arguably, when talking about «null-string» constructor, it might be useful to read about which strings are considered null, and which methods one can use to test that. Change-Id: Ie30144f33000aac53f4041cfb99da28a79dad946 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QString: use char16_t in ucstr{n,i,}cmp & ucstreq instead of QCharThiago Macieira2022-01-181-26/+24
| | | | | Change-Id: I0e5f6bec596a4a78bd3bfffd16c907b827f08519 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: optimize equalStrings() with a template in ucstrncmp()Thiago Macieira2022-01-181-6/+27
| | | | | | | | | If the SIMD code has already determined that the byte content differs, we don't need to actually subtract the bytes we loaded from memory in vector operations to return a sorting result. Change-Id: I0e5f6bec596a4a78bd3bfffd16c908b2902e1b1b Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: merge the two ucstrcmp overloads into a templateThiago Macieira2022-01-181-11/+8
| | | | | | | So we don't accidentally make modifications to one and not the other. Change-Id: I0e5f6bec596a4a78bd3bfffd16c94f1025aea521 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: introduce ucstreq() to optimize equalStrings()Thiago Macieira2022-01-181-2/+15
| | | | | | | | | If the lengths aren't equal, the strings can't be equal either, so we can skip the entire comparison. Some of the front-end functions that call these entry points already check for this, actually. Change-Id: Ib42b3adc93bf4d43bd55fffd16c8ceb9594512f2 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: make ucstricmp() parameters match the compareStrings'Thiago Macieira2022-01-181-27/+20
| | | | | | | | | | | | | The compareStrings() entry points take QStringView and QLatin1String, which are both ordered [size, pointer], so match that in the ucstricmp() parameters. This further reduces the prologue of the compareStrings() functions before reaching the case-sensitive comparison. There's no need to do the same for the case-sensitive functions because they're getting inlined. Change-Id: I0e5f6bec596a4a78bd3bfffd16c8ffc980c8af0c Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: add Q_NEVER_INLINE for ucstricmp()Thiago Macieira2022-01-181-3/+3
| | | | | | | | | | | | | | | Case-insensitive comparisons are not common, but both GCC and Clang inlined the ucstricmp() functions into QtPrivate::compareStrings(), with the side-effect that a lot of unnecessary setup code saving CPU registers was executed in the prologue of those functions. After this, Clang 13 emits both compareString() functions without any push/pop to save registers on x86-64; GCC 11 still emits a few, but fewer than before (it's emitting some unnecessary overhead for the loops). Change-Id: I0e5f6bec596a4a78bd3bfffd16c8fc2c0be9165f Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: remove the old unaligned 4-byte compares in ucstrncmp()Thiago Macieira2022-01-181-60/+9
| | | | | | | | | | | | | This is very old code, predating the public Qt history (Qt 4.5). It predates all other SIMD code in qstring.cpp, actually. Now that we do have implementations for MIPS DSP, ARM Neon and x86 SSE2, this content has very little value. It would be relevant for other architectures Qt still supports (POWER and RISC-V come to mind), but I guess the compiler's auto-vectorizer functionality can do a better job than this content. Change-Id: I0e5f6bec596a4a78bd3bfffd16c90733fb0d8f22 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Restore std::as_const() where a qAsConst was lost between 5.15 and 6Edward Welbourne2022-01-181-2/+2
| | | | | | | | | | Amends commit 837a29b0b92c72b7b9d66a427c24a9fa8037f4f4's fix for shadowing to take account of the loss of const-qualification of uiLanguages where it was then used in a ranged-for loop. Pick-to: 6.3 6.2 Change-Id: Ic4021bd9917cb27832a197126cc80a7f384a14a2 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString::toLatin1_helper_inplace: simplify the codeThiago Macieira2022-01-172-21/+21
| | | | | | | | | Hot function, so help the compiler out. In particular, this removes any touch to the ref count, so there are no atomic operations or dead code leading to memory allocations and deallocations. Change-Id: I0e5f6bec596a4a78bd3bfffd16c9a0fbd8dd2c12 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QVersionNumber: port fromString() to QAnyStringViewMarc Mutz2022-01-181-1/+1
| | | | | | | | | | | | | | | | | We can handle the UTF-8 case by reinterpreting it as Latin-1. This way, the suffixIndex stays valid as a return value. As a drive-by, optimize away toLatin1() calls by using a QVLA. We really need a better way of converting UTF-16 -> L1 than qt_to_latin1()... [ChangeLog][QtCore][QVersionNumber] fromString() now takes QAnyStringView (was: QString, QStringView, QLatin1String) and a qsizetype pointer (was: int pointer). Change-Id: I86abaadba2792658fbf93ccd1e0b86e3302c697c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QLatin1String: perform the comparison to another QL1S using memcmp()Thiago Macieira2022-01-171-4/+4
| | | | | | | | | | | | | | | | | | qstrncmp() would stop at the first null character, which isn't correct. The tests that had been disabled in tst_qstring.cpp (with an inaccurate comment) were actually passing. I've added one more to ensure that the terminating null is compared where needed. [ChangeLog][QtCore][QLatin1String and QUtf8StringView] Fixed a couple of bugs where two QLatin1Strings or two QUtf8StringViews would stop their comparisons at the first embedded null character, instead of comparing the full string. This issue affected both classes' relational operators (less than, greater than, etc.) and QUtf8StringView's operator== and operator!=. Pick-to: 5.15 6.2 6.3 Change-Id: I0e5f6bec596a4a78bd3bfffd16c90ecea71ea68e Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QAnyStringView: fix code point -> code unit in the docsGiuseppe D'Angelo2022-01-161-1/+1
| | | | | | | | | | The docs are saying that QAnyStringView sizes are measured in terms of code units of the underlying encoding, not code points. Pick-to: 6.3 6.2 Change-Id: Ic72ffd122e45631e8626c9d57ec24ca348918424 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Fix warning on macOS builds, unbreak -developer-buildVolker Hilsheimer2022-01-141-1/+1
| | | | | | | | | | | The mix of signed (qsizetype) and unsigned long when comparing breaks local -Werror,-Wsign-compare builds. Amends d83dbc3db2f305e745cd75a9fd9c97128eaac42f. Change-Id: I7910b7e2dfaaa01d8069ce52e97c0166e6d3fa30 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Tidy up macOS collation and add some assertionsEdward Welbourne2022-01-131-7/+9
| | | | | Change-Id: I7af21ce38f2f23498d7c8a7e027bfffb149a43e3 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* QString::compare: fix comparing a 4GB string to 1 QCharThiago Macieira2022-01-121-1/+1
| | | | | | | | | | If the size() was larger than INT_MAX, the result would be wrong (and UB). Pick-to: 6.2 6.3 Change-Id: I0e5f6bec596a4a78bd3bfffd16c99763e66c2013 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QByteArray: remove left-over Q_NEVER_INLINE after we removed the tablesThiago Macieira2022-01-121-4/+0
| | | | | | | | | | | | | | | | | | The comment made a reference to the case tables that used to exist in qbytearray.cpp prior to commit 9dd8e655cdd26eeaae30645b7fe013d9a696547f ("Limit QByteArray's 8-bit support to ASCII"). Now that the parameter is a function pointer, not a table, inlining is actually beneficial: we definitely don't want the compiler to emit function calls via the function pointer. At least GCC 11 was already doing constant-propagation of the parameter: While it didn't inline the function, it cloned it and propagated the constant in each of the two clones. There were 4 copies of this function: const and non-const, upper and lower. Change-Id: I0e5f6bec596a4a78bd3bfffd16c912a16602e20a Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QByteArray: fix append() with a negative lengthThiago Macieira2022-01-111-2/+2
| | | | | | | | | | | | The documentation says that if it's negative, we find the null termination. This bug was introduced with the clean up to use QByteArrayView in commit 8897aa071a668563a53a4c2e6909572f1762b1e7. Fixes: QTBUG-99640 Pick-to: 6.3 6.2 Change-Id: Ib42b3adc93bf4d43bd55fffd16c89fa4a960f3a9 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QByteArray: avoid detach() in a no-op replace()Marc Mutz2022-01-031-2/+3
| | | | | | | | | | | | | When the the replacement has the same size as the replacee, but that size is zero, the whole operation is a no-op, and there's no need to detach(). [ChangeLog][QtCore][QByteArray] A replace(pos, n, after) call no longer detach()es when n == after.size() == 0. Pick-to: 6.3 6.2 Change-Id: I1e8d7c7fb6383f8bfea3212e49fca8a128535564 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* QLocale: replace use of append(QString(n, c)) with resize(size() + n, c)Marc Mutz2021-12-281-1/+1
| | | | | | | Avoids a temporary QString creation. Change-Id: Ibc87a3f1bf2979780e4a2cce7e1757f97c39a9be Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QLocale: replace a few getData() with viewData()Marc Mutz2021-12-281-5/+5
| | | | | | | | | | Both multi-arg as well as QStringBuilder support QStringView these days, so there's no need for a temporary QString, even one fromRawData(), with all its extra codegen, when QStringView can do the job just fine. Change-Id: Ie9031aef85c5f0b535e94d9e414b7bd71ad909f7 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QString: reorganize some template functionsThiago Macieira2021-12-231-192/+185
| | | | | | | | | | | | This is going to screw up the git blame functionality (which is why they were forward-declared instead of implemented on-site) but the alternative is that Qt Creator thinks qstring.cpp had almost no functions inside. Pick-to: 6.3 6.2 Task-number: QTCREATORBUG-25594 Change-Id: Ib42b3adc93bf4d43bd55fffd16c1986f1a3c1574 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QStringBuilder: handle freeSpaceAtBegin() in op+=Marc Mutz2021-12-211-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Amends 9b320edb535a0fbe118933d2e983b73f90c32685. The above commit made the mistake of relying on the 30yr+ old fundamental relation size() - capacity() == freeSpaceAtEnd() which, however, Qt 6's prepend()-optimization (freeSpaceAtBegin()) broke. Because of that, while size() - capacity() may be large enough to hold the new data, if freeSpaceAtBegin() > 0, then freeSpaceAtEnd() may not. Fix by inspecting freeSpaceAtEnd() instead of capacity(). The following reserve() call is unaffected, since it internally already adds freeSpaceAtBegin() to the requested size, which is why the unconditional reserve() in 9b320edb535a0fbe118933d2e983b73f90c32685^ worked while 9b320edb535a0fbe118933d2e983b73f90c32685's capacity() check did not. Fixes: QTBUG-99330 Pick-to: 6.2 6.3 Change-Id: I520f36216011423f97a24484263acd40d8b1fa43 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Topi Reiniö <topi.reinio@qt.io> Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
* QString: use char16_t in isAscii() instead of QCharThiago Macieira2021-12-181-15/+19
| | | | | | | | | Drive-by simple clarification of the code that needed to be touched anyway. Pick-to: 6.3 6.2 Change-Id: Ib42b3adc93bf4d43bd55fffd16c14f984b0fb592 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: don't let the compiler emit unnecessary loopingThiago Macieira2021-12-181-0/+6
| | | | | | | | | When AVX2 was enabled, we know we don't need to loop in qt_is_ascii() (QtPrivate::isAscii(QLatin1String)). Pick-to: 6.3 6.2 Change-Id: Ib42b3adc93bf4d43bd55fffd16c14f8f95ae8678 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString: replace an #if with ifThiago Macieira2021-12-181-6/+4
| | | | | | Pick-to: 6.3 6.2 Change-Id: Ib42b3adc93bf4d43bd55fffd16c111291d1e8ddd Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QStringBuilder: fix quadratic behavior in op+=Marc Mutz2021-12-171-2/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QByteArray and QString honor a reserve(n) faithfully, meaning that if n > capacity(), then capacity() == n after the reserve() call. This is expected behavior, and also what libstdc++'s std::vector does. The problem is QStringBuilder's op+=, which calls reserve() unconditionally to ensure capacity for its resize-after-append magic. If a user builds up a string by repeatedly appending string-builder expressions, these repeated minimal-progress reserve calls destroy the string's natural geometric capacity growth, turning it linear instead, and hence the whole construction becomes quadratic. Fix by calling reserve() only when necessary, and for a maximum of O(logN) times, N being the separate calls to QStringBuilder's op+=. This guarantees amortized-linear runtime of string building again. Need to insert an explicit detach() call in reserve()'s stead, lest a detach() in the following data() would reset capacity() to size(). Copied a useful comment from the QByteArray case to the QString case. [ChangeLog][QtCore][QStringBuilder] Fixed quadratic behavior when repeatedly appending string-builder expressions (using operator+=) to QString/QByteArray objects. Pick-to: 6.3 6.2 Change-Id: I1c210a8d0026c227e55e5e30a46fb747660bb66e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru>
* QByteArray: fix UB (precondition violation) in replace()Marc Mutz2021-12-171-1/+3
| | | | | | | | | | | | | | | | | If after.isNull(), then we called memcpy with a nullptr, which is UB, even if the size is zero, too. memmove() has the same precondition. Fix by guarding the memcpy() call with an explicit length check. The Qt 5.15 code is sufficiently different to not attempt to pick there. Pick-to: 6.3 6.2 Change-Id: I86a2f00ede6ca8fab8d4222f84dccf375c4a2194 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QByteArray: optimize replace() a bitMarc Mutz2021-12-171-1/+1
| | | | | | | | These days, we perform the alias check unconditionally, so the remainder of the function can assume that *this and after do not overlap. So memcpy() suffices, we don't need memmove(). Pick-to: 6.3 6.2 Change-Id: Ib6966facfe643b0aaf50d902709f5fe926bed527 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QString: scope a loop variable correctlyMarc Mutz2021-12-161-3/+2
| | | | | | | | The variable idx isn't used outside the respective loops, so make it loop-local. Change-Id: I62807cb244b068ce4df42812a0e4b99a1f488adc Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru>
* QString: fix UB (pointer arithmetic on nullptr) in qLastIndexOfMarc Mutz2021-12-161-1/+1
| | | | | | | | | | | | | | | | | | | | Says ubsan: qstring.cpp:10484:17: runtime error: applying non-zero offset 18446744073709551614 to null pointer If we search for a null needle, we stored 0-1 in a size_t variable and unconditionally appied that offset to the needle's data() pointer. That being the nullptr, ubsan complained. To fix, set sl_minus_1 to 0 if it would underflow. In that case, sl_minus_1, n, and h, are not used, anyway, so their values don't matter as long as we don't invoke UB. Pick-to: 6.3 6.2 5.15 Change-Id: Idca4e845c77838dfc84acdb68bbbc98382b5e1d5 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QByteArray: sprinkle API with noexceptMarc Mutz2021-12-142-42/+22
| | | | | | | | | | | Mark (const) data()/begin()/end()/size()/empty() and similar as noexcept. Move some trivial definitions into the class body. Pick-to: 6.3 Change-Id: I6f3ab792264347cdc6a476dacecf065f59f16ff9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QLocale: Extend support for language codesIevgenii Meshcheriakov2021-12-096-357/+533
| | | | | | | | | | | | | | | | | | | | | | | | | | | This commit extends functionality for QLocale::codeToLanguage() and QLocale::languageToCode() by adding an additional argument that allows selection of the ISO 639 code-set to consider for those operations. The following ISO 639 codes are supported: * Part 1 * Part 2 bibliographic * Part 2 terminological * Part 3 As a result of this change the codeToLanguage() overload without the additional argument now returns a Language value if it matches any know code. Previously a valid language was returned only if the function argument matched the first code defined for that language from the above list. [ChangeLog][QtCore][QLocale] Added overloads for codeToLanguage() and languageToCode() that support specifying which ISO 639 codes to consider. Fixes: QTBUG-98129 Change-Id: I4da8a89e2e68a673cf63a621359cded609873fa2 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QStringBuilder: Add support for QByteArrayViewMårten Nordheim2021-12-041-0/+21
| | | | | | | [ChangeLog][QtCore][QStringBuilder] Added support for QByteArrayView. Change-Id: If2c23549d533dd31c320f3ee455fcd01ea5b460a Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QString et al: fix lastIndexOf() API asymmetryMarc Mutz2021-12-024-4/+25
| | | | | | | | | | | | | | | | | Commit 6cee204d56205e250b0675c9c6d4dd8a2367f3c4 introduced overloads of lastIndexOf() which drop the 'from' argument, inadvertently fixing QTBUG-80694, but failed to provide the new overloads for all existing lastIndexOf() overloads, making the fix for QTBUG-80694 incomplete. This patch completes the fix, by adding the missing overloads (for char-likes) and also adds the missing (non-regex) tests to tst_qstringapisymmetry. Also amends 1c164ec7f21a78025475c561a70b94d1e3dd6bb6. Fixes: QTBUG-80694 Change-Id: Ib4b3d597d658ce2edf01a2bce0d711ecea593d6e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QString::arg: deprecate use of arbitrary Unicode digits as replacementsGiuseppe D'Angelo2021-11-301-4/+80
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The only documented replacements for Q*String*::arg() are sequences like %1, %2, %3 -- where the n-th number is expressed using a sequence of ASCII digits [1]. The code parsing the replacements however used the QChar::digitValue() function. That function simply checks if a QChar has a *Unicode digit value* (no matter what its block/category is), and if so, returns the corresponding digit value as an int (otherwise returns -1). The result of this is that a sequence like "%¹" or "%१" actually triggered substitutions (both count as "1"). Similarly, QChars with a digit value would be parsed as part of longer sequences like "%1²" (counting as "12" (!)). This behavior is weird, undocumented, and extremely likely the usual backstabbing by Unicode by using "convenience" QChar methods -- that is, never *intended* by the implementation. This commit deprecates (via warnings) such usages, which for the time being are left working as before (in the name of backwards compatibility). At the same time: given it's extremely unlikely that someone would be deliberately relying on this behavior, it implements the desired change of behavior (only accept sequences of ASCII digits) starting from Qt 6.6, that is, after the next LTS. Throughout Qt 6's lifetime users will still be able to control arg()'s behavior by setting an env variable, but that variable (and the support for Unicode digits) will disappear in Qt 7. To summarize: * Qt 6.3->6.5: default is Unicode digits, env var to control * Qt 6.6->6.x: default is ASCII digits, env var to control * Qt 7: only ASCII digits, no env var [1] That's the name Unicode gives to them, cf. https://www.unicode.org/charts/PDF/U0000.pdf [ChangeLog][QtCore][Deprecation Notices] The arg() functions featured in Qt string classes have always been documented to require replacements tokens to be sequences of ASCII digits (like %1, %2, %34, and so on). A coding oversight made it accept sequences of arbitrary characters with a Unicode digit value instead. For instance, "%2੩" is interpreted as the 23rd substitution; and "%1²" is interpreted as the 12th substitution. This behavior is deprecated, and will result in runtime warnings. Starting from Qt 6.6, arg()'s behavior will be changed to accept only ASCII digits by default. That means that "%1²" is going to be interpreted as substitution number 1 followed by the "²" character (which does not get substituted, so it gets left as-is in the result). Users can restore the previous semantics (accept Unicode digits) by setting the QT_USE_UNICODE_DIGIT_VALUES_IN_STRING_ARG environment variable to a non-zero value. In Qt 7, arg() will only support sequences of ASCII digits. Note that from Qt 6.3 users can also set QT_USE_UNICODE_DIGIT_VALUES_IN_STRING_ARG to zero; this will make arg() use ASCII digits only, in preparation for the future change of defaults. Change-Id: I8a044b629bcca6996e76018c9faf7c6748ae04e8 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>