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>
bb10
parent
daceee6a90
commit
97890c9ab4
|
|
@ -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')));
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue