summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-11-02 11:42:39 -0700
committerMarc Mutz <marc.mutz@qt.io>2023-02-20 17:30:44 +0000
commit97890c9ab4d63b9ee7e62287dd6bdd4bd2323677 (patch)
tree2b0da5e9e4ecf1c57953cc48456223fd3f8e6bec /src/corelib/text
parentdaceee6a9004565cee6ccd50c6a96216066b4f29 (diff)
QLocale: modernize ascii_isspace() to C++17
And on 64-bit platforms, use a 64-bit integer, which removes a subtraction from the matching code. The loop in bytearrayToLongLong() looks like, on x86-64: movabsq $4294983168, %rsi .L1217: movzbl (%rdx), %ecx cmpl $64, %ecx ja .L1216 btq %rcx, %rsi jnc .L1216 incq %rdx cmpq %rbx, %rdx jne .L1217 Change-Id: I3d74c753055744deb8acfffd1723d8b51e151432 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qlocale.cpp2
-rw-r--r--src/corelib/text/qlocale_p.h67
2 files changed, 61 insertions, 8 deletions
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 0714434d2d..a80f982330 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -79,7 +79,7 @@ static_assert(!ascii_isspace('\a'));
static_assert(!ascii_isspace('a'));
static_assert(!ascii_isspace('\177'));
static_assert(!ascii_isspace(uchar('\200')));
-static_assert(!ascii_isspace(uchar('\xA0')));
+static_assert(!ascii_isspace(uchar('\xA0'))); // NBSP (is a space but Latin 1, not ASCII)
static_assert(!ascii_isspace(uchar('\377')));
/******************************************************************************
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index 831bfe9eda..2509193ba9 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -28,9 +28,67 @@
#include <limits>
#include <cmath>
+#include <string_view>
QT_BEGIN_NAMESPACE
+template <typename MaskType, uchar Lowest> struct QCharacterSetMatch
+{
+ static constexpr int MaxRange = std::numeric_limits<MaskType>::digits;
+ MaskType mask;
+
+ constexpr QCharacterSetMatch(std::string_view set)
+ : mask(0)
+ {
+ for (char c : set) {
+ int idx = uchar(c) - Lowest;
+ mask |= MaskType(1) << idx;
+ }
+ }
+
+ constexpr bool matches(uchar c) const
+ {
+ unsigned idx = c - Lowest;
+ if (idx >= MaxRange)
+ return false;
+ return (mask >> idx) & 1;
+ }
+};
+
+namespace {
+static constexpr char ascii_space_chars[] =
+ "\t" // 9: HT - horizontal tab
+ "\n" // 10: LF - line feed
+ "\v" // 11: VT - vertical tab
+ "\f" // 12: FF - form feed
+ "\r" // 13: CR - carriage return
+ " "; // 32: space
+
+template <const char *Set, int ForcedLowest = -1> static constexpr auto makeCharacterSetMatch()
+{
+ constexpr auto view = std::string_view(Set);
+ constexpr uchar MinElement = *std::min_element(view.begin(), view.end());
+ constexpr uchar MaxElement = *std::max_element(view.begin(), view.end());
+ constexpr int Range = MaxElement - MinElement;
+ static_assert(Range < 64, "Characters in the set are 64 or more values apart");
+
+ if constexpr (ForcedLowest >= 0) {
+ // use the force
+ static_assert(ForcedLowest <= int(MinElement), "The force is not with you");
+ using MaskType = std::conditional_t<MaxElement - ForcedLowest < 32, quint32, quint64>;
+ return QCharacterSetMatch<MaskType, ForcedLowest>(view);
+ } else if constexpr (MaxElement < std::numeric_limits<qregisteruint>::digits) {
+ // if we can use a Lowest of zero, we can remove a subtraction
+ // from the matches() code at runtime
+ using MaskType = std::conditional_t<(MaxElement < 32), quint32, qregisteruint>;
+ return QCharacterSetMatch<MaskType, 0>(view);
+ } else {
+ using MaskType = std::conditional_t<(Range < 32), quint32, quint64>;
+ return QCharacterSetMatch<MaskType, MinElement>(view);
+ }
+}
+} // unnamed namespace
+
struct QLocaleData;
// Subclassed by Android platform plugin:
class Q_CORE_EXPORT QSystemLocale
@@ -477,15 +535,10 @@ QString qt_readEscapedFormatString(QStringView format, qsizetype *idx);
QStringView *script = nullptr, QStringView *cntry = nullptr);
[[nodiscard]] qsizetype qt_repeatCount(QStringView s);
-enum { AsciiSpaceMask = (1u << (' ' - 1)) |
- (1u << ('\t' - 1)) | // 9: HT - horizontal tab
- (1u << ('\n' - 1)) | // 10: LF - line feed
- (1u << ('\v' - 1)) | // 11: VT - vertical tab
- (1u << ('\f' - 1)) | // 12: FF - form feed
- (1u << ('\r' - 1)) }; // 13: CR - carriage return
[[nodiscard]] constexpr inline bool ascii_isspace(uchar c)
{
- return c >= 1u && c <= 32u && (AsciiSpaceMask >> uint(c - 1)) & 1u;
+ constexpr auto matcher = makeCharacterSetMatch<ascii_space_chars>();
+ return matcher.matches(c);
}
QT_END_NAMESPACE