QXmpp Version: 1.10.0
QXmppUtils_p.h
1// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
2// SPDX-FileCopyrightText: 2022 Melvin Keskin <melvo@olomono.de>
3//
4// SPDX-License-Identifier: LGPL-2.1-or-later
5
6#ifndef QXMPPUTILS_P_H
7#define QXMPPUTILS_P_H
8
9#include "QXmppGlobal.h"
10
11#include <array>
12#include <functional>
13#include <optional>
14#include <stdint.h>
15
16#include <QByteArray>
17#include <QDomElement>
18
19class QDomElement;
20class QXmlStreamWriter;
21class QXmppNonza;
22
23namespace QXmpp::Private {
24
25// std::array helper
26namespace detail {
27 template<class T, std::size_t N, std::size_t... I>
28 constexpr std::array<std::remove_cv_t<T>, N>
29 to_array_impl(T (&&a)[N], std::index_sequence<I...>)
30 {
31 return { { std::move(a[I])... } };
32 }
33} // namespace detail
34
35template<class T, std::size_t N>
36constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&&a)[N])
37{
38 return detail::to_array_impl(std::move(a), std::make_index_sequence<N> {});
39}
40
41// Helper for Q(Any)StringView overloads that were added later
42inline auto toString60(QStringView s)
43{
44#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
45 return s;
46#else
47 return s.toString();
48#endif
49}
50inline auto toString65(QStringView s)
51{
52#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
53 return s;
54#else
55 return s.toString();
56#endif
57}
58
59// QStringLiteral for Qt < 6.5, otherwise uses string view
60#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
61#define QSL65(text) u"" text
62#else
63#define QSL65(text) QStringLiteral(text)
64#endif
65
66// Enum parsing
67template<typename Enum, std::size_t N>
68std::optional<Enum> enumFromString(const std::array<QStringView, N> &values, QStringView str)
69{
70 auto itr = std::find(values.begin(), values.end(), str);
71 if (itr != values.end()) {
72 return Enum(std::distance(values.begin(), itr));
73 }
74 return {};
75}
76
77// XML streams
78void writeOptionalXmlAttribute(QXmlStreamWriter *stream, QStringView name, QStringView value);
79void writeXmlTextElement(QXmlStreamWriter *stream, QStringView name, QStringView value);
80void writeXmlTextElement(QXmlStreamWriter *writer, QStringView name, QStringView xmlns, QStringView value);
81void writeOptionalXmlTextElement(QXmlStreamWriter *writer, QStringView name, QStringView value);
82void writeEmptyElement(QXmlStreamWriter *writer, QStringView name, QStringView xmlns);
83template<typename T>
84inline void writeOptional(QXmlStreamWriter *writer, const std::optional<T> &value)
85{
86 if (value) {
87 value->toXml(writer);
88 }
89}
90
91// Base64
92std::optional<QByteArray> parseBase64(const QString &);
93inline QString serializeBase64(const QByteArray &data) { return QString::fromUtf8(data.toBase64()); }
94
95// Integer parsing
96template<typename Int>
97std::optional<Int> parseInt(QStringView str);
98template<typename Int>
99inline QString serializeInt(Int value) { return QString::number(value); }
100
101// Booleans
102std::optional<bool> parseBoolean(const QString &str);
103QString serializeBoolean(bool);
104
105//
106// DOM
107//
108
109QXMPP_EXPORT bool isIqType(const QDomElement &, QStringView tagName, QStringView xmlns);
110QXMPP_EXPORT QDomElement firstChildElement(const QDomElement &, QStringView tagName = {}, QStringView xmlNs = {});
111QXMPP_EXPORT QDomElement nextSiblingElement(const QDomElement &, QStringView tagName = {}, QStringView xmlNs = {});
112
113struct DomChildElements {
114 QDomElement parent;
115 QStringView tagName;
116 QStringView namespaceUri;
117
118 struct EndIterator { };
119 struct Iterator {
120 Iterator operator++()
121 {
122 el = nextSiblingElement(el, tagName, namespaceUri);
123 return *this;
124 }
125 bool operator!=(EndIterator) const { return !el.isNull(); }
126 const QDomElement &operator*() const { return el; }
127
128 QDomElement el;
129 QStringView tagName;
130 QStringView namespaceUri;
131 };
132
133 Iterator begin() const { return { firstChildElement(parent, tagName, namespaceUri), tagName, namespaceUri }; }
134 EndIterator end() const { return {}; }
135};
136
137inline DomChildElements iterChildElements(const QDomElement &el, QStringView tagName = {}, QStringView namespaceUri = {}) { return DomChildElements { el, tagName, namespaceUri }; }
138
139std::vector<QString> parseTextElements(DomChildElements elements);
140
141QByteArray serializeXml(const void *packet, void (*toXml)(const void *, QXmlStreamWriter *));
142template<typename T>
143inline QByteArray serializeXml(const T &packet)
144{
145 return serializeXml(&packet, [](const void *packet, QXmlStreamWriter *w) {
146 std::invoke(&T::toXml, reinterpret_cast<const T *>(packet), w);
147 });
148}
149
150QXMPP_EXPORT QByteArray generateRandomBytes(uint32_t minimumByteCount, uint32_t maximumByteCount);
151QXMPP_EXPORT void generateRandomBytes(uint8_t *bytes, uint32_t byteCount);
152float calculateProgress(qint64 transferred, qint64 total);
153
154QXMPP_EXPORT std::pair<QString, int> parseHostAddress(const QString &address);
155
156} // namespace QXmpp::Private
157
158#endif // QXMPPUTILS_P_H
Definition: QXmppNonza.h:14