QtBase  v6.3.1
qanystringview.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 #ifndef QANYSTRINGVIEW_H
40 #define QANYSTRINGVIEW_H
41 
42 #include <QtCore/qstringview.h>
43 #include <QtCore/qutf8stringview.h>
44 
45 #ifdef __cpp_impl_three_way_comparison
46 #include <compare>
47 #endif
48 #include <limits>
49 
51 
52 template <typename, typename> class QStringBuilder;
53 template <typename> struct QConcatenable;
54 
56 {
57 public:
60 private:
61  template <typename Char>
62  using if_compatible_char = std::enable_if_t<std::disjunction_v<
65  >, bool>;
66 
67  template <typename Pointer>
68  using if_compatible_pointer = std::enable_if_t<std::disjunction_v<
71  >, bool>;
72 
73 
74  template <typename T>
75  using if_compatible_container = std::enable_if_t<std::disjunction_v<
78  >, bool>;
79 
80  // confirm we don't make an accidental copy constructor:
83 
84  template <typename Char>
85  static constexpr std::size_t encodeType(qsizetype sz) noexcept
86  {
87  // only deals with Utf8 and Utf16 - there's only one way to create
88  // a Latin1 string, and that ctor deals with the tag itself
89  Q_ASSERT(sz >= 0);
90  Q_ASSERT(sz <= qsizetype(SizeMask));
91  return std::size_t(sz) | uint(sizeof(Char) == sizeof(char16_t)) * Tag::Utf16;
92  }
93 
94  template <typename Char>
95  static qsizetype lengthHelperPointer(const Char *str) noexcept
96  {
97 #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
98  if (__builtin_constant_p(*str)) {
99  qsizetype result = 0;
100  while (*str++ != u'\0')
101  ++result;
102  return result;
103  }
104 #endif
105  if constexpr (sizeof(Char) == sizeof(char16_t))
106  return QtPrivate::qustrlen(reinterpret_cast<const char16_t*>(str));
107  else
108  return qsizetype(strlen(reinterpret_cast<const char*>(str)));
109  }
110 
111  template <typename Container>
112  static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
113  {
114  return qsizetype(std::size(c));
115  }
116 
117  template <typename Char, size_t N>
118  static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept
119  {
120  const auto it = std::char_traits<Char>::find(str, N, Char(0));
121  const auto end = it ? it : std::next(str, N);
122  return qsizetype(std::distance(str, end));
123  }
124 
125  static QChar toQChar(char ch) noexcept { return toQChar(QLatin1Char{ch}); } // we don't handle UTF-8 multibytes
126  static QChar toQChar(QChar ch) noexcept { return ch; }
127  static QChar toQChar(QLatin1Char ch) noexcept { return ch; }
128 
129  explicit constexpr QAnyStringView(const void *d, qsizetype n, std::size_t sizeAndType) noexcept
130  : m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {}
131 public:
132  constexpr QAnyStringView() noexcept
133  : m_data{nullptr}, m_size{0} {}
134  constexpr QAnyStringView(std::nullptr_t) noexcept
135  : QAnyStringView() {}
136 
137  template <typename Char, if_compatible_char<Char> = true>
138  constexpr QAnyStringView(const Char *str, qsizetype len)
139  : m_data{str},
140  m_size{encodeType<Char>((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len))} {}
141 
142  template <typename Char, if_compatible_char<Char> = true>
143  constexpr QAnyStringView(const Char *f, const Char *l)
144  : QAnyStringView(f, l - f) {}
145 
146 #ifdef Q_CLANG_QDOC
147  template <typename Char, size_t N>
148  constexpr QAnyStringView(const Char (&array)[N]) noexcept;
149 
150  template <typename Char>
151  constexpr QAnyStringView(const Char *str) noexcept;
152 #else
153 
154  template <typename Pointer, if_compatible_pointer<Pointer> = true>
155  constexpr QAnyStringView(const Pointer &str) noexcept
156  : QAnyStringView{str, str ? lengthHelperPointer(str) : 0} {}
157 #endif
158 
159  // defined in qstring.h
160  inline QAnyStringView(const QByteArray &str) noexcept; // TODO: Should we have this at all? Remove?
161  inline QAnyStringView(const QString &str) noexcept;
162  inline constexpr QAnyStringView(QLatin1String str) noexcept;
163 
164  // defined in qstringbuilder.h
165  template <typename A, typename B>
166  inline QAnyStringView(const QStringBuilder<A, B> &expr,
167  typename QConcatenable<QStringBuilder<A, B>>::ConvertTo &&capacity = {});
168 
169  template <typename Container, if_compatible_container<Container> = true>
170  constexpr QAnyStringView(const Container &c) noexcept
171  : QAnyStringView(std::data(c), lengthHelperContainer(c)) {}
172 
173  template <typename Char, if_compatible_char<Char> = true>
174  constexpr QAnyStringView(const Char &c) noexcept
175  : QAnyStringView{&c, 1} {}
176  constexpr QAnyStringView(const QChar &c) noexcept
177  : QAnyStringView{&c, 1} {}
178 
179  template <typename Char, typename Container = decltype(QChar::fromUcs4(U'x')),
180  std::enable_if_t<std::is_same_v<Char, char32_t>, bool> = true>
181  constexpr QAnyStringView(Char c, Container &&capacity = {})
182  : QAnyStringView(capacity = QChar::fromUcs4(c)) {}
183 
184  constexpr QAnyStringView(QStringView v) noexcept
185  : QAnyStringView(std::data(v), lengthHelperContainer(v)) {}
186 
187  template <bool UseChar8T>
189  : QAnyStringView(std::data(v), lengthHelperContainer(v)) {}
190 
191  template <typename Char, size_t Size, if_compatible_char<Char> = true>
192  [[nodiscard]] constexpr static QAnyStringView fromArray(const Char (&string)[Size]) noexcept
193  { return QAnyStringView(string, Size); }
194 
195  // defined in qstring.h:
196  template <typename Visitor>
197  inline constexpr decltype(auto) visit(Visitor &&v) const;
198 
199  [[nodiscard]] inline QString toString() const; // defined in qstring.h
200 
201  [[nodiscard]] constexpr qsizetype size() const noexcept { return qsizetype(m_size & SizeMask); }
202  [[nodiscard]] constexpr const void *data() const noexcept { return m_data; }
203 
204  [[nodiscard]] Q_CORE_EXPORT static int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
205  [[nodiscard]] Q_CORE_EXPORT static bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept;
206 
207  //
208  // STL compatibility API:
209  //
210  [[nodiscard]] constexpr QChar front() const; // NOT noexcept!
211  [[nodiscard]] constexpr QChar back() const; // NOT noexcept!
212  [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
213  [[nodiscard]] constexpr qsizetype size_bytes() const noexcept
214  { return size() * charSize(); }
215 
216  //
217  // Qt compatibility API:
218  //
219  [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
220  [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
221  [[nodiscard]] constexpr qsizetype length() const noexcept
222  { return size(); }
223 
224 private:
225  [[nodiscard]] friend inline bool operator==(QAnyStringView lhs, QAnyStringView rhs) noexcept
226  { return QAnyStringView::equal(lhs, rhs); }
227  [[nodiscard]] friend inline bool operator!=(QAnyStringView lhs, QAnyStringView rhs) noexcept
228  { return !QAnyStringView::equal(lhs, rhs); }
229 
230 #if defined(__cpp_impl_three_way_comparison) && !defined(Q_QDOC)
231  [[nodiscard]] friend inline auto operator<=>(QAnyStringView lhs, QAnyStringView rhs) noexcept
232  { return QAnyStringView::compare(lhs, rhs) <=> 0; }
233 #else
234  [[nodiscard]] friend inline bool operator<=(QAnyStringView lhs, QAnyStringView rhs) noexcept
235  { return QAnyStringView::compare(lhs, rhs) <= 0; }
236  [[nodiscard]] friend inline bool operator>=(QAnyStringView lhs, QAnyStringView rhs) noexcept
237  { return QAnyStringView::compare(lhs, rhs) >= 0; }
238  [[nodiscard]] friend inline bool operator<(QAnyStringView lhs, QAnyStringView rhs) noexcept
239  { return QAnyStringView::compare(lhs, rhs) < 0; }
240  [[nodiscard]] friend inline bool operator>(QAnyStringView lhs, QAnyStringView rhs) noexcept
241  { return QAnyStringView::compare(lhs, rhs) > 0; }
242 #endif
243 
244  // TODO: Optimize by inverting and storing the flags in the low bits and
245  // the size in the high.
246  static_assert(std::is_same_v<std::size_t, size_t>);
247  static_assert(sizeof(size_t) == sizeof(qsizetype));
248  static constexpr size_t SizeMask = (std::numeric_limits<size_t>::max)() / 4;
249  static constexpr size_t Latin1Flag = SizeMask + 1;
250  static constexpr size_t TwoByteCodePointFlag = Latin1Flag << 1;
251  static constexpr size_t TypeMask = (std::numeric_limits<size_t>::max)() & ~SizeMask;
252  static_assert(TypeMask == (Latin1Flag|TwoByteCodePointFlag));
253  // HI HI LO LO ...
254  // 0 0 SZ SZ Utf8
255  // 0 1 SZ SZ Latin1
256  // 1 0 SZ SZ Utf16
257  // 1 1 SZ SZ Unused
258  // ^ ^ latin1
259  // | sizeof code-point == 2
260  enum Tag : size_t {
261  Utf8 = 0,
262  Latin1 = Latin1Flag,
263  Utf16 = TwoByteCodePointFlag,
264  Unused = TypeMask,
265  };
266  [[nodiscard]] constexpr Tag tag() const noexcept { return Tag{m_size & TypeMask}; }
267  [[nodiscard]] constexpr bool isUtf16() const noexcept { return tag() == Tag::Utf16; }
268  [[nodiscard]] constexpr bool isUtf8() const noexcept { return tag() == Tag::Utf8; }
269  [[nodiscard]] constexpr bool isLatin1() const noexcept { return tag() == Tag::Latin1; }
270  [[nodiscard]] constexpr QStringView asStringView() const
271  { return Q_ASSERT(isUtf16()), QStringView{m_data_utf16, size()}; }
272  [[nodiscard]] constexpr q_no_char8_t::QUtf8StringView asUtf8StringView() const
273  { return Q_ASSERT(isUtf8()), q_no_char8_t::QUtf8StringView{m_data_utf8, size()}; }
274  [[nodiscard]] inline constexpr QLatin1String asLatin1StringView() const;
275  [[nodiscard]] constexpr size_t charSize() const noexcept { return isUtf16() ? 2 : 1; }
276  Q_ALWAYS_INLINE constexpr void verify(qsizetype pos, qsizetype n = 0) const
277  {
278  Q_ASSERT(pos >= 0);
279  Q_ASSERT(pos <= size());
280  Q_ASSERT(n >= 0);
281  Q_ASSERT(n <= size() - pos);
282  }
283  union {
284  const void *m_data;
285  const char *m_data_utf8;
286  const char16_t *m_data_utf16;
287  };
288  size_t m_size;
289 };
291 
292 template <typename QStringLike, std::enable_if_t<std::disjunction_v<
293  std::is_same<QStringLike, QString>,
294  std::is_same<QStringLike, QByteArray>
295  >, bool> = true>
296 [[nodiscard]] inline QAnyStringView qToAnyStringViewIgnoringNull(const QStringLike &s) noexcept
297 { return QAnyStringView(s.data(), s.size()); }
298 
300 
301 #endif /* QANYSTRINGVIEW_H */
small capitals from c petite p scientific f u
Definition: afcover.h:88
constexpr QAnyStringView(const QChar &c) noexcept
constexpr QChar back() const
Definition: qstring.h:381
friend bool operator!=(QAnyStringView lhs, QAnyStringView rhs) noexcept
constexpr static QAnyStringView fromArray(const Char(&string)[Size]) noexcept
friend bool operator>=(QAnyStringView lhs, QAnyStringView rhs) noexcept
const char * m_data_utf8
constexpr const void * data() const noexcept
constexpr qsizetype size() const noexcept
constexpr QAnyStringView(const Char *str, qsizetype len)
QString toString() const
Definition: qstring.h:1204
qsizetype size_type
static Q_CORE_EXPORT int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Definition: qstring.cpp:1636
constexpr bool isEmpty() const noexcept
constexpr QAnyStringView(const Char &c) noexcept
static Q_CORE_EXPORT bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept
Definition: qstring.cpp:1476
const void * m_data
qptrdiff difference_type
constexpr qsizetype size_bytes() const noexcept
constexpr bool isNull() const noexcept
constexpr QAnyStringView() noexcept
const char16_t * m_data_utf16
constexpr QAnyStringView(const Char *f, const Char *l)
constexpr QChar front() const
Definition: qstring.h:377
constexpr QAnyStringView(std::nullptr_t) noexcept
constexpr QAnyStringView(QStringView v) noexcept
constexpr decltype(auto) visit(Visitor &&v) const
constexpr QAnyStringView(const Container &c) noexcept
friend bool operator>(QAnyStringView lhs, QAnyStringView rhs) noexcept
constexpr QAnyStringView(Char c, Container &&capacity={})
friend bool operator<(QAnyStringView lhs, QAnyStringView rhs) noexcept
friend bool operator<=(QAnyStringView lhs, QAnyStringView rhs) noexcept
constexpr bool empty() const noexcept
constexpr QAnyStringView(const Pointer &str) noexcept
constexpr qsizetype length() const noexcept
friend bool operator==(QAnyStringView lhs, QAnyStringView rhs) noexcept
constexpr QAnyStringView(QBasicUtf8StringView< UseChar8T > v) noexcept
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
static constexpr auto fromUcs4(char32_t c) noexcept
Definition: qstringview.h:485
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QStringView class provides a unified view on UTF-16 strings with a read-only subset of the QStrin...
Definition: qstringview.h:122
QString str
[2]
auto it unsigned count const
Definition: hb-iter.hh:848
short next
Definition: keywords.cpp:454
#define inline
Definition: md4c.c:45
CaseSensitivity
Definition: qnamespace.h:1282
@ CaseSensitive
Definition: qnamespace.h:1284
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const char16_t *str) noexcept
Definition: qstring.cpp:351
IsCompatibleChar8TypeHelper< std::remove_cv_t< std::remove_reference_t< Char > >> IsCompatibleChar8Type
int distance(TestIterator &a, TestIterator &b)
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
Q_DECLARE_TYPEINFO(QAnyStringView, Q_PRIMITIVE_TYPE)
QAnyStringView qToAnyStringViewIgnoringNull(const QStringLike &s) noexcept
ptrdiff_t qptrdiff
Definition: qglobal.h:307
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLfloat GLfloat f
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
const GLubyte * c
Definition: qopenglext.h:12701
GLenum array
Definition: qopenglext.h:7028
GLenum GLsizei len
Definition: qopenglext.h:3292
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QT_BEGIN_NAMESPACE typedef char Char
@ Q_PRIMITIVE_TYPE
Definition: qtypeinfo.h:155
QBasicUtf8StringView< false > QUtf8StringView
QStringList::Iterator it
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
Definition: data.cpp:95
#define rhs
QDomElement find(const QString &tagName, const QDomElement &e)
Definition: main.cpp:39