5#ifndef QANYSTRINGVIEW_H
6#define QANYSTRINGVIEW_H
8#include <QtCore/qcompare.h>
9#include <QtCore/qcontainerfwd.h>
10#include <QtCore/qlatin1stringview.h>
11#include <QtCore/qstringview.h>
12#include <QtCore/qutf8stringview.h>
14#include <QtCore/q20type_traits.h>
17class tst_QAnyStringView;
23template <
typename Tag,
typename Result>
26template <
typename Tag,
typename Result>
29template <
typename Char>
36#if QT_VERSION >= QT_VERSION_CHECK(7
, 0
, 0
) || defined(QT_BOOTSTRAPPED)
37# define QT_ANYSTRINGVIEW_TAG_IN_LOWER_BITS
47#ifdef QT_ANYSTRINGVIEW_TAG_IN_LOWER_BITS
51 static constexpr int SizeShift = 0;
52 static constexpr size_t Latin1Flag = SizeMask + 1;
54 static constexpr size_t TwoByteCodePointFlag = Latin1Flag << 1;
55 static constexpr size_t TypeMask = ~(SizeMask << SizeShift);
56 static_assert(TypeMask == (Latin1Flag|TwoByteCodePointFlag));
68 Utf16 = TwoByteCodePointFlag,
72 template <
typename Char>
77 template <
typename Char>
83 template <
typename Char>
114 template<
typename Char>
115 static constexpr bool isAsciiOnlyCharsAtCompileTime(Char *str, qsizetype sz)
noexcept
118 if (!q20::is_constant_evaluated())
120 if constexpr (
sizeof(Char) !=
sizeof(
char)) {
125 for (qsizetype i = 0; i < sz; ++i) {
126 if (uchar(str[i]) > 0x7f)
133 template<
typename Char>
134 static constexpr std::size_t encodeType(
const Char *str, qsizetype sz)
noexcept
138 Q_ASSERT(sz <= qsizetype(SizeMask));
139 Q_ASSERT(str || !sz);
140 return (
std::size_t(sz) << SizeShift)
141 | uint(
sizeof(Char) ==
sizeof(
char16_t)) * Tag::Utf16
142 | uint(isAsciiOnlyCharsAtCompileTime(str, sz)) * Tag::Latin1;
145 template <
typename Char>
146 static constexpr qsizetype lengthHelperPointer(
const Char *str)
noexcept
148 if (q20::is_constant_evaluated())
149 return QtPrivate::lengthHelperPointer(str);
150 if constexpr (
sizeof(Char) ==
sizeof(
char16_t))
151 return QtPrivate::qustrlen(
reinterpret_cast<
const char16_t*>(str));
153 return qsizetype(strlen(
reinterpret_cast<
const char*>(str)));
156 static QChar toQChar(
char ch)
noexcept {
return toQChar(QLatin1Char{ch}); }
157 static QChar toQChar(QChar ch)
noexcept {
return ch; }
158 static QChar toQChar(QLatin1Char ch)
noexcept {
return ch; }
160 struct QCharContainer {
161 explicit QCharContainer() =
default;
165 template <
typename Char>
166 static constexpr QAnyStringView fromCharInternal(
const Char &ch)
noexcept
168 if constexpr (
sizeof ch == 1)
169 return QAnyStringView{&ch, 1, size_t{Tag::Latin1}};
174 explicit constexpr QAnyStringView(
const void *d, qsizetype n,
std::size_t sizeAndType)
noexcept
175 :
m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {}
182 template <
typename Char, if_compatible_char<Char> =
true>
188 template <
typename Char, if_compatible_char<Char> =
true>
196 template <
typename Char>
199 template <
typename Pointer, if_compatible_pointer<Pointer> =
true>
203 template <
typename Char, if_compatible_char<Char> =
true>
217 template <
typename Container, if_convertible_to<QString, Container> =
true>
218 constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QString> &&capacity = {})
222 template <
typename Container, if_convertible_to<QByteArray, Container> =
true>
223 constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {})
227 template <
typename Char, if_compatible_char<Char> =
true>
230 template <
typename Char, if_convertible_to<QChar, Char> =
true>
231 constexpr QAnyStringView(Char ch, QCharContainer &&capacity = QCharContainer())
noexcept
233 template <
typename Char,
typename Container =
decltype(
QChar::
fromUcs4(U'x')),
234 if_compatible_utf32_char<Char> =
true>
257 auto result = QContainerImplHelper::mid(size(), &pos, &n);
258 return result == QContainerImplHelper::Null ? QAnyStringView() : sliced(pos, n);
263 if (size_t(n) >= size_t(size()))
270 if (size_t(n) >= size_t(size()))
272 return sliced(size() - n, n);
276 { verify(pos, 0);
auto r = *
this; r.advanceData(pos); r.decreaseSize(pos);
return r; }
278 { verify(pos, n);
auto r = *
this; r.advanceData(pos); r.setSize(n);
return r; }
280 { verify(0, n);
return sliced(0, n); }
282 { verify(0, n);
return sliced(size() - n, n); }
284 { verify(0, n);
return sliced(0, size() - n); }
287 { *
this = sliced(pos);
return *
this; }
289 { *
this = sliced(pos, n);
return *
this; }
292 { verify(0, n); setSize(n); }
293 constexpr void chop(qsizetype n)
294 { verify(0, n); decreaseSize(n); }
296 template <
typename...Args>
297 [[nodiscard]]
inline QString arg(Args &&...args)
const;
302 {
return qsizetype((m_size >> SizeShift) & SizeMask); }
303 [[
nodiscard]]
constexpr const void *
data()
const noexcept {
return m_data; }
309#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
323 {
return size() * charSize(); }
328 return QtPrivate::MaxAllocSize / charSize() - 1;
341 {
return QAnyStringView::equal(lhs, rhs); }
345 const int res = QAnyStringView::compare(lhs, rhs);
346 return Qt::compareThreeWay(res, 0);
350#ifndef QT_NO_DEBUG_STREAM
354 [[
nodiscard]]
constexpr Tag tag()
const noexcept {
return Tag{m_size & TypeMask}; }
355 [[
nodiscard]]
constexpr bool isUtf16()
const noexcept {
return tag() == Tag::Utf16; }
356 [[
nodiscard]]
constexpr bool isUtf8()
const noexcept {
return tag() == Tag::Utf8; }
357 [[
nodiscard]]
constexpr bool isLatin1()
const noexcept {
return tag() == Tag::Latin1; }
358 [[
nodiscard]]
constexpr QStringView asStringView()
const
359 {
return Q_ASSERT(isUtf16()), QStringView{m_data_utf16, size()}; }
360 [[
nodiscard]]
constexpr q_no_char8_t::QUtf8StringView asUtf8StringView()
const
361 {
return Q_ASSERT(isUtf8()), q_no_char8_t::QUtf8StringView{m_data_utf8, size()}; }
362 [[
nodiscard]]
inline constexpr QLatin1StringView asLatin1StringView()
const;
363 [[
nodiscard]]
constexpr size_t charSize()
const noexcept {
return isUtf16() ? 2 : 1; }
364 constexpr void setSize(qsizetype sz)
noexcept { m_size = size_t(sz) | tag(); }
365 constexpr void decreaseSize(qsizetype delta)
noexcept
370 constexpr void advanceData(qsizetype delta)
noexcept
371 { m_data_utf8 += delta * charSize(); }
372 Q_ALWAYS_INLINE
constexpr void verify([[maybe_unused]] qsizetype pos = 0,
373 [[maybe_unused]] qsizetype n = 1)
const
376 Q_ASSERT(pos <= size());
378 Q_ASSERT(n <= size() - pos);
386 friend class ::tst_QAnyStringView;
390template <
typename QStringLike, std::enable_if_t<std::disjunction_v<
391 std::is_same<QStringLike, QString>,
392 std::is_same<QStringLike, QByteArray>
394[[nodiscard]]
inline QAnyStringView qToAnyStringViewIgnoringNull(
const QStringLike &s)
noexcept
395{
return QAnyStringView(s.begin(), s.size()); }
constexpr QChar back() const
Returns the last character in the string view.
constexpr QAnyStringView(Char c, Container &&capacity={}) noexcept
constexpr const void * data() const noexcept
Returns a const pointer to the first character in the string view.
constexpr QAnyStringView sliced(qsizetype pos, qsizetype n) const
static constexpr bool detects_US_ASCII_at_compile_time
constexpr QAnyStringView left(qsizetype n) const
constexpr QAnyStringView(Char ch, QCharContainer &&capacity=QCharContainer()) noexcept
constexpr QAnyStringView & slice(qsizetype pos)
constexpr QAnyStringView last(qsizetype n) const
constexpr qsizetype size() const noexcept
Returns the size of this string view, in the encoding's code points.
constexpr QAnyStringView & slice(qsizetype pos, qsizetype n)
constexpr QAnyStringView(const Char *str, qsizetype len)
Constructs a string view on str with length len.
QString toString() const
Returns a deep copy of this string view's data as a QString.
qsizetype size_type
Alias for qsizetype.
constexpr QAnyStringView first(qsizetype n) const
constexpr QAnyStringView right(qsizetype n) const
static Q_CORE_EXPORT int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Compares the string view lhs with the string view rhs and returns a negative integer if lhs is less t...
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
static Q_CORE_EXPORT bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept
friend bool comparesEqual(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept
qptrdiff difference_type
Alias for {std::ptrdiff_t}.
constexpr qsizetype size_bytes() const noexcept
Returns the size of this string view, but in bytes, not code-points.
constexpr QAnyStringView sliced(qsizetype pos) const
constexpr QAnyStringView mid(qsizetype pos, qsizetype n=-1) const
constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t< Container, QString > &&capacity={})
constexpr QAnyStringView chopped(qsizetype n) const
constexpr bool isNull() const noexcept
Returns whether this string view is null - that is, whether {data() == nullptr}.
constexpr QAnyStringView() noexcept
Constructs a null string view.
const char16_t * m_data_utf16
constexpr QAnyStringView(const Char *f, const Char *l)
Constructs a string view on first with length (last - first).
constexpr QChar front() const
Returns the first character in the string view.
QString arg(Args &&...args) const
constexpr QAnyStringView(std::nullptr_t) noexcept
Constructs a null string view.
constexpr void chop(qsizetype n)
constexpr void truncate(qsizetype n)
constexpr QAnyStringView(QLatin1StringView str) noexcept
constexpr QAnyStringView(const Char(&str)[]) noexcept
constexpr bool empty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
constexpr QAnyStringView(const Pointer &str) noexcept
constexpr qsizetype length() const noexcept
Same as size().
constexpr qsizetype max_size() const noexcept
friend Qt::strong_ordering compareThreeWay(const QAnyStringView &lhs, const QAnyStringView &rhs) noexcept
QAnyStringView(const QByteArray &str) noexcept
Constructs a string view on str.
typename wrapped< Tag, Result >::type wrapped_t
QDebug operator<<(QDebug d, QAnyStringView s)
Q_DECLARE_TYPEINFO(QAnyStringView, Q_PRIMITIVE_TYPE)