QXmpp  Version: 1.10.4
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 
19 class QDomElement;
20 class QXmlStreamWriter;
21 class QXmppNonza;
22 
23 namespace QXmpp::Private {
24 
25 // std::array helper
26 namespace 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 
35 template<class T, std::size_t N>
36 constexpr 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
42 inline 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 }
50 inline 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
67 template<typename Enum, std::size_t N>
68 std::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
78 void writeOptionalXmlAttribute(QXmlStreamWriter *stream, QStringView name, QStringView value);
79 void writeXmlTextElement(QXmlStreamWriter *stream, QStringView name, QStringView value);
80 void writeXmlTextElement(QXmlStreamWriter *writer, QStringView name, QStringView xmlns, QStringView value);
81 void writeOptionalXmlTextElement(QXmlStreamWriter *writer, QStringView name, QStringView value);
82 void writeEmptyElement(QXmlStreamWriter *writer, QStringView name, QStringView xmlns);
83 template<typename T>
84 inline void writeOptional(QXmlStreamWriter *writer, const std::optional<T> &value)
85 {
86  if (value) {
87  value->toXml(writer);
88  }
89 }
90 
91 // Base64
92 std::optional<QByteArray> parseBase64(const QString &);
93 inline QString serializeBase64(const QByteArray &data) { return QString::fromUtf8(data.toBase64()); }
94 
95 // Integer parsing
96 template<typename Int>
97 std::optional<Int> parseInt(QStringView str);
98 template<typename Int>
99 inline QString serializeInt(Int value) { return QString::number(value); }
100 
101 // Booleans
102 std::optional<bool> parseBoolean(const QString &str);
103 QString serializeBoolean(bool);
104 
105 //
106 // DOM
107 //
108 
109 QXMPP_EXPORT bool isIqType(const QDomElement &, QStringView tagName, QStringView xmlns);
110 QXMPP_EXPORT QDomElement firstChildElement(const QDomElement &, QStringView tagName = {}, QStringView xmlNs = {});
111 QXMPP_EXPORT QDomElement nextSiblingElement(const QDomElement &, QStringView tagName = {}, QStringView xmlNs = {});
112 
113 struct 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 
137 inline DomChildElements iterChildElements(const QDomElement &el, QStringView tagName = {}, QStringView namespaceUri = {}) { return DomChildElements { el, tagName, namespaceUri }; }
138 
139 std::vector<QString> parseTextElements(DomChildElements elements);
140 
141 QByteArray serializeXml(const void *packet, void (*toXml)(const void *, QXmlStreamWriter *));
142 template<typename T>
143 inline 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 
150 QXMPP_EXPORT QByteArray generateRandomBytes(size_t minimumByteCount, size_t maximumByteCount);
151 QXMPP_EXPORT void generateRandomBytes(uint8_t *bytes, size_t byteCount);
152 float calculateProgress(qint64 transferred, qint64 total);
153 
154 QXMPP_EXPORT std::pair<QString, int> parseHostAddress(const QString &address);
155 
156 } // namespace QXmpp::Private
157 
158 #endif // QXMPPUTILS_P_H
Definition: QXmppNonza.h:13
Definition: Algorithms.h:12