diff options
Diffstat (limited to 'src/qmltyperegistrar/qanystringviewutils_p.h')
-rw-r--r-- | src/qmltyperegistrar/qanystringviewutils_p.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/qmltyperegistrar/qanystringviewutils_p.h b/src/qmltyperegistrar/qanystringviewutils_p.h new file mode 100644 index 0000000000..22c4bd63a0 --- /dev/null +++ b/src/qmltyperegistrar/qanystringviewutils_p.h @@ -0,0 +1,187 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef QANYSTRINGVIEWUTILS_P_H +#define QANYSTRINGVIEWUTILS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include <QtCore/private/qjson_p.h> + +#include <QtCore/qanystringview.h> +#include <QtCore/qcbormap.h> +#include <QtCore/qcborvalue.h> + +QT_BEGIN_NAMESPACE + +namespace QAnyStringViewUtils { + +inline QAnyStringView toStringView(const QCborValue &value) +{ + const QCborContainerPrivate *container = QJsonPrivate::Value::container(value); + if (!container) + return QAnyStringView(); + + const qint64 n = QJsonPrivate::Value::valueHelper(value); + const auto &e = container->elements.at(n); + const auto data = container->byteData(e); + if (!data) + return QAnyStringView(); + if (e.flags & QtCbor::Element::StringIsUtf16) + return data->asStringView(); + if (e.flags & QtCbor::Element::StringIsAscii) + return data->asLatin1(); + return data->asUtf8StringView(); +} + +inline QAnyStringView toStringView(const QCborMap &map, QLatin1StringView key) +{ + return toStringView(map[key]); +} + +// Note: This only works if part is US-ASCII, but there is no type to encode this information! +inline bool endsWith(QAnyStringView whole, QLatin1StringView part) +{ + Q_ASSERT(QtPrivate::isAscii(part)); + return whole.length() >= part.length() && whole.last(part.length()) == part; +} + +// Note: This only works if part is US-ASCII, but there is no type to encode this information! +inline bool startsWith(QAnyStringView whole, QLatin1StringView part) +{ + Q_ASSERT(QtPrivate::isAscii(part)); + return whole.length() >= part.length() && whole.first(part.length()) == part; +} + +inline bool doesContain(QStringView whole, QLatin1Char part) { return whole.contains(part); } +inline bool doesContain(QLatin1StringView whole, QLatin1Char part) { return whole.contains(part); } +inline bool doesContain(QUtf8StringView whole, QLatin1Char part) +{ + return QByteArrayView(whole.data(), whole.size()).contains(part.toLatin1()); +} +inline bool contains(QAnyStringView whole, QLatin1Char part) +{ + return whole.visit([&](auto view) { return doesContain(view, part); }); +} + +inline qsizetype getLastIndexOf(QStringView whole, QLatin1StringView part) +{ + return whole.lastIndexOf(part); +} +inline qsizetype getLastIndexOf(QLatin1StringView whole, QLatin1StringView part) +{ + return whole.lastIndexOf(part); +} +inline qsizetype getLastIndexOf(QUtf8StringView whole, QLatin1StringView part) +{ + return QByteArrayView(whole.data(), whole.size()).lastIndexOf(part); +} +inline qsizetype lastIndexOf(QAnyStringView whole, QLatin1StringView part) +{ + Q_ASSERT(QtPrivate::isAscii(part)); + return whole.visit([&](auto view) { return getLastIndexOf(view, part); }); +} + +inline int toInt(QUtf8StringView view) +{ + return QByteArrayView(view.data(), view.length()).toInt(); +} +inline int toInt(QLatin1StringView view) { return view.toInt(); } +inline int toInt(QStringView view) { return view.toInt(); } + +inline int toInt(QAnyStringView string) +{ + return string.visit([](auto view) { return toInt(view); }); +} + +template<typename StringView> +QAnyStringView doTrimmed(StringView string) +{ + if constexpr (std::is_same_v<StringView, QStringView>) + return string.trimmed(); + if constexpr (std::is_same_v<StringView, QLatin1StringView>) + return string.trimmed(); + if constexpr (std::is_same_v<StringView, QUtf8StringView>) + return QByteArrayView(string.data(), string.length()).trimmed(); +} + + +inline QAnyStringView trimmed(QAnyStringView string) +{ + return string.visit([](auto data) { + return doTrimmed(data); + }); +} + +template<typename StringView, typename Handler> +auto processAsUtf8(StringView string, Handler &&handler) +{ + if constexpr (std::is_same_v<StringView, QStringView>) + return handler(QByteArrayView(string.toUtf8())); + if constexpr (std::is_same_v<StringView, QLatin1StringView>) + return handler(QByteArrayView(string.data(), string.length())); + if constexpr (std::is_same_v<StringView, QUtf8StringView>) + return handler(QByteArrayView(string.data(), string.length())); + if constexpr (std::is_same_v<StringView, QByteArrayView>) + return handler(string); + if constexpr (std::is_same_v<StringView, QByteArray>) + return handler(QByteArrayView(string)); + if constexpr (std::is_same_v<StringView, QAnyStringView>) { + + // Handler is: + // * a reference if an lvalue ref is passed + // * a value otherwise + // We conserve its nature for passing to the lambda below. + // This is necessary because we need to decide on the nature of + // the lambda capture as part of the syntax (prefix '&' or not). + // So we always pass a reference-conserving wrapper as value. + struct Wrapper { Handler handler; }; + + return string.visit([w = Wrapper { std::forward<Handler>(handler) }](auto view) mutable { + static_assert(!(std::is_same_v<decltype(view), QAnyStringView>)); + return processAsUtf8(std::move(view), std::forward<Handler>(w.handler)); + }); + } + Q_UNREACHABLE(); +} + +// Note: This only works if sep is US-ASCII, but there is no type to encode this information! +inline QList<QAnyStringView> split(QAnyStringView source, QLatin1StringView sep) +{ + Q_ASSERT(QtPrivate::isAscii(sep)); + + QList<QAnyStringView> list; + if (source.isEmpty()) { + list.append(source); + return list; + } + + qsizetype start = 0; + qsizetype end = source.length(); + + for (qsizetype current = 0; current < end; ++current) { + if (source.mid(current, sep.length()) == sep) { + list.append(source.mid(start, current - start)); + start = current + sep.length(); + } + } + + if (start < end) + list.append(source.mid(start, end - start)); + + return list; +} + +} + +QT_END_NAMESPACE + +#endif // QANYSTRINGVIEWUTILS_P_H |