1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#ifndef QANYSTRINGVIEWUTILS_P_H
5#define QANYSTRINGVIEWUTILS_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16
17#include <QtCore/private/qjson_p.h>
18
19#include <QtCore/qanystringview.h>
20
21QT_BEGIN_NAMESPACE
22
23namespace QAnyStringViewUtils {
24
25// Note: This only works if part is US-ASCII, but there is no type to encode this information!
26inline bool endsWith(QAnyStringView whole, QLatin1StringView part)
27{
28 Q_ASSERT(QtPrivate::isAscii(part));
29 return whole.length() >= part.length() && whole.last(n: part.length()) == part;
30}
31
32// Note: This only works if part is US-ASCII, but there is no type to encode this information!
33inline bool startsWith(QAnyStringView whole, QLatin1StringView part)
34{
35 Q_ASSERT(QtPrivate::isAscii(part));
36 return whole.length() >= part.length() && whole.first(n: part.length()) == part;
37}
38
39inline bool doesContain(QStringView whole, QLatin1Char part) { return whole.contains(c: part); }
40inline bool doesContain(QLatin1StringView whole, QLatin1Char part) { return whole.contains(c: part); }
41inline bool doesContain(QUtf8StringView whole, QLatin1Char part)
42{
43 return QByteArrayView(whole.data(), whole.size()).contains(c: part.toLatin1());
44}
45inline bool contains(QAnyStringView whole, QLatin1Char part)
46{
47 return whole.visit(v: [&](auto view) { return doesContain(view, part); });
48}
49
50inline qsizetype getLastIndexOf(QStringView whole, QLatin1StringView part)
51{
52 return whole.lastIndexOf(s: part);
53}
54inline qsizetype getLastIndexOf(QLatin1StringView whole, QLatin1StringView part)
55{
56 return whole.lastIndexOf(s: part);
57}
58inline qsizetype getLastIndexOf(QUtf8StringView whole, QLatin1StringView part)
59{
60 return QByteArrayView(whole.data(), whole.size()).lastIndexOf(a: part);
61}
62inline qsizetype lastIndexOf(QAnyStringView whole, QLatin1StringView part)
63{
64 Q_ASSERT(QtPrivate::isAscii(part));
65 return whole.visit(v: [&](auto view) { return getLastIndexOf(view, part); });
66}
67
68inline int toInt(QUtf8StringView view)
69{
70 return QByteArrayView(view.data(), view.length()).toInt();
71}
72inline int toInt(QLatin1StringView view) { return view.toInt(); }
73inline int toInt(QStringView view) { return view.toInt(); }
74
75inline int toInt(QAnyStringView string)
76{
77 return string.visit(v: [](auto view) { return toInt(view); });
78}
79
80template<typename StringView>
81QAnyStringView doTrimmed(StringView string)
82{
83 if constexpr (std::is_same_v<StringView, QStringView>)
84 return string.trimmed();
85 if constexpr (std::is_same_v<StringView, QLatin1StringView>)
86 return string.trimmed();
87 if constexpr (std::is_same_v<StringView, QUtf8StringView>)
88 return QByteArrayView(string.data(), string.length()).trimmed();
89}
90
91
92inline QAnyStringView trimmed(QAnyStringView string)
93{
94 return string.visit(v: [](auto data) {
95 return doTrimmed(data);
96 });
97}
98
99template<typename StringView, typename Handler>
100auto processAsUtf8(StringView string, Handler &&handler)
101{
102 if constexpr (std::is_same_v<StringView, QStringView>)
103 return handler(QByteArrayView(string.toUtf8()));
104 if constexpr (std::is_same_v<StringView, QLatin1StringView>)
105 return handler(QByteArrayView(string.data(), string.length()));
106 if constexpr (std::is_same_v<StringView, QUtf8StringView>)
107 return handler(QByteArrayView(string.data(), string.length()));
108 if constexpr (std::is_same_v<StringView, QByteArrayView>)
109 return handler(string);
110 if constexpr (std::is_same_v<StringView, QByteArray>)
111 return handler(QByteArrayView(string));
112 if constexpr (std::is_same_v<StringView, QAnyStringView>) {
113
114 // Handler is:
115 // * a reference if an lvalue ref is passed
116 // * a value otherwise
117 // We conserve its nature for passing to the lambda below.
118 // This is necessary because we need to decide on the nature of
119 // the lambda capture as part of the syntax (prefix '&' or not).
120 // So we always pass a reference-conserving wrapper as value.
121 struct Wrapper { Handler handler; };
122
123 return string.visit([w = Wrapper { std::forward<Handler>(handler) }](auto view) mutable {
124 static_assert(!(std::is_same_v<decltype(view), QAnyStringView>));
125 return processAsUtf8(std::move(view), std::forward<Handler>(w.handler));
126 });
127 }
128 Q_UNREACHABLE();
129}
130
131// Note: This only works if sep is US-ASCII, but there is no type to encode this information!
132inline QList<QAnyStringView> split(QAnyStringView source, QLatin1StringView sep)
133{
134 Q_ASSERT(QtPrivate::isAscii(sep));
135
136 QList<QAnyStringView> list;
137 if (source.isEmpty()) {
138 list.append(t: source);
139 return list;
140 }
141
142 qsizetype start = 0;
143 qsizetype end = source.length();
144
145 for (qsizetype current = 0; current < end; ++current) {
146 if (source.mid(pos: current, n: sep.length()) == sep) {
147 list.append(t: source.mid(pos: start, n: current - start));
148 start = current + sep.length();
149 }
150 }
151
152 if (start < end)
153 list.append(t: source.mid(pos: start, n: end - start));
154
155 return list;
156}
157
158}
159
160QT_END_NAMESPACE
161
162#endif // QANYSTRINGVIEWUTILS_P_H
163

source code of qtdeclarative/src/qmltyperegistrar/qanystringviewutils_p.h