summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qlocale_tools.cpp
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2021-07-20 17:06:49 +0200
committerMårten Nordheim <marten.nordheim@qt.io>2021-07-26 20:43:44 +0000
commit5d0542a356be1c47e2f99e6ba38b8e520ca0710c (patch)
tree1e756b3dbb83f211d330106d5203cbfdf95c327d /src/corelib/text/qlocale_tools.cpp
parent7ff72d0a0f1f4964e4d4fd250283711fc51db016 (diff)
QString::number(int): Avoid going through qlocale machinery
For increased performance, as measured with the number_qu?longlong QString benchmarks. The results are all good, reducing runtime by anywhere between 40 and 220 nanoseconds. The slowest test previously completing at ~330ns, now completing at ~105ns. Task-number: QTBUG-88484 Change-Id: Ie96e86e57b635bac01389aed531a6d9f087df983 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/text/qlocale_tools.cpp')
-rw-r--r--src/corelib/text/qlocale_tools.cpp92
1 files changed, 48 insertions, 44 deletions
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index 24a6bcfd09..bdb00d3696 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -460,6 +460,53 @@ qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
return result;
}
+static Q_ALWAYS_INLINE void qulltoBasicLatin_helper(qulonglong number, int base, char16_t *&p)
+{
+ // Performance-optimized code. Compiler can generate faster code when base is known.
+ switch (base) {
+#define BIG_BASE_LOOP(b) \
+ do { \
+ const int r = number % b; \
+ *--p = (r < 10 ? u'0' : u'a' - 10) + r; \
+ number /= b; \
+ } while (number)
+#ifndef __OPTIMIZE_SIZE__
+#define SMALL_BASE_LOOP(b) \
+ do { \
+ *--p = u'0' + number % b; \
+ number /= b; \
+ } while (number)
+
+ case 2: SMALL_BASE_LOOP(2); break;
+ case 8: SMALL_BASE_LOOP(8); break;
+ case 10: SMALL_BASE_LOOP(10); break;
+ case 16: BIG_BASE_LOOP(16); break;
+#undef SMALL_BASE_LOOP
+#endif
+ default: BIG_BASE_LOOP(base); break;
+#undef BIG_BASE_LOOP
+ }
+}
+
+// This is technically "qulonglong to ascii", but that name's taken
+QString qulltoBasicLatin(qulonglong number, int base, bool negative)
+{
+ if (number == 0)
+ return QStringLiteral("0");
+ // Length of MIN_LLONG with the sign in front is 65; we never need surrogate pairs.
+ // We do not need a terminator.
+ const unsigned maxlen = 65;
+ static_assert(CHAR_BIT * sizeof(number) + 1 <= maxlen);
+ char16_t buff[maxlen];
+ char16_t *const end = buff + maxlen, *p = end;
+
+ qulltoBasicLatin_helper(number, base, p);
+ if (negative)
+ *--p = u'-';
+
+ return QString(reinterpret_cast<QChar *>(p), end - p);
+}
+
QString qulltoa(qulonglong number, int base, const QStringView zero)
{
// Length of MAX_ULLONG in base 2 is 64; and we may need a surrogate pair
@@ -469,51 +516,8 @@ QString qulltoa(qulonglong number, int base, const QStringView zero)
char16_t buff[maxlen];
char16_t *const end = buff + maxlen, *p = end;
- // Performance-optimized code. Compiler can generate faster code when base is known.
if (base != 10 || zero == u"0") {
- switch (base) {
-#ifndef __OPTIMIZE_SIZE__
- case 10:
- while (number != 0) {
- const int c = number % 10;
- const qulonglong temp = number / 10;
- *--p = '0' + c;
- number = temp;
- }
- break;
- case 2:
- while (number != 0) {
- const int c = number % 2;
- const qulonglong temp = number / 2;
- *--p = '0' + c;
- number = temp;
- }
- break;
- case 8:
- while (number != 0) {
- const int c = number % 8;
- const qulonglong temp = number / 8;
- *--p = '0' + c;
- number = temp;
- }
- break;
- case 16:
- while (number != 0) {
- const int c = number % 16;
- const qulonglong temp = number / 16;
- *--p = c < 10 ? '0' + c : c - 10 + 'a';
- number = temp;
- }
- break;
-#endif
- default:
- while (number != 0) {
- const int c = number % base;
- const qulonglong temp = number / base;
- *--p = c < 10 ? '0' + c : c - 10 + 'a';
- number = temp;
- }
- }
+ qulltoBasicLatin_helper(number, base, p);
} else if (zero.size() && !zero.at(0).isSurrogate()) {
const char16_t zeroUcs2 = zero.at(0).unicode();
while (number != 0) {