1// Copyright (C) 2017 Lorenz Haas
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qmqtttopicname.h"
5
6#include <QtCore/QDebug>
7
8QT_BEGIN_NAMESPACE
9
10/*!
11 \class QMqttTopicName
12 \inmodule QtMqtt
13 \reentrant
14 \ingroup shared
15
16 \brief The QMqttTopicName class represents a MQTT topic name.
17
18 QMqttTopicName is a thin wrapper around a QString providing an expressive
19 data type for MQTT topic names. Beside the benefits of having a strong type
20 preventing unintended misuse, QMqttTopicName provides convenient functions
21 related to topic names like isValid() or levels().
22
23 \sa QMqttTopicFilter
24 */
25
26/*!
27 \fn void QMqttTopicName::swap(QMqttTopicName &other)
28 Swaps the MQTT topic name \a other with this MQTT topic name. This
29 operation is very fast and never fails.
30 */
31
32class QMqttTopicNamePrivate : public QSharedData
33{
34public:
35 QString name;
36};
37
38/*!
39 Creates a new MQTT topic name with the specified \a name.
40 */
41QMqttTopicName::QMqttTopicName(const QString &name) : d(new QMqttTopicNamePrivate)
42{
43 d->name = name;
44}
45
46/*!
47 Creates a new MQTT topic name with the specified \a name.
48 */
49QMqttTopicName::QMqttTopicName(const QLatin1String &name) : d(new QMqttTopicNamePrivate)
50{
51 d->name = name;
52}
53
54/*!
55 Creates a new MQTT topic name as a copy of \a name.
56 */
57QMqttTopicName::QMqttTopicName(const QMqttTopicName &name) : d(name.d)
58{
59}
60
61/*!
62 Destroys the QMqttTopicName object.
63 */
64QMqttTopicName::~QMqttTopicName()
65{
66}
67
68/*!
69 Assigns the MQTT topic name \a name to this object, and returns a reference
70 to the copy.
71 */
72QMqttTopicName &QMqttTopicName::operator=(const QMqttTopicName &name)
73{
74 d = name.d;
75 return *this;
76}
77
78/*!
79 Returns the topic name.
80 */
81QString QMqttTopicName::name() const
82{
83 return d->name;
84}
85
86/*!
87 Sets the topic name to \a name.
88 */
89void QMqttTopicName::setName(const QString &name)
90{
91 d.detach();
92 d->name = name;
93}
94
95/*!
96 Returns \c true if the topic name is valid according to the MQTT standard
97 section 4.7, or \c false otherwise.
98 */
99bool QMqttTopicName::isValid() const
100{
101 const int bytes = d->name.size();
102 return bytes > 0 // [MQTT-4.7.3-1]
103 && bytes < 65536 // [MQTT-4.7.3-3]
104 && !d->name.contains(c: QLatin1Char('#')) // [MQTT-4.7.1-1]
105 && !d->name.contains(c: QLatin1Char('+')) // [MQTT-4.7.1-1]
106 && !d->name.contains(c: QChar(QChar::Null)); // [MQTT-4.7.3-2]
107}
108
109/*!
110 Returns the total number of topic levels.
111 */
112int QMqttTopicName::levelCount() const
113{
114 return d->name.isEmpty() ? 0 : d->name.count(c: QLatin1Char('/')) + 1;
115}
116
117/*!
118 Returns the topic levels.
119 */
120QStringList QMqttTopicName::levels() const
121{
122 return d->name.split(sep: QLatin1Char('/'), behavior: Qt::KeepEmptyParts);
123}
124
125/*!
126 //! friend
127 \fn bool QMqttTopicName::operator==(const QMqttTopicName &lhs, const QMqttTopicName &rhs)
128
129 Returns \c true if the topic names \a lhs and \a rhs are equal,
130 otherwise returns \c false.
131 */
132bool operator==(const QMqttTopicName &lhs, const QMqttTopicName &rhs) Q_DECL_NOTHROW
133{
134 return (lhs.d == rhs.d) || (lhs.d->name == rhs.d->name);
135}
136
137/*!
138 //! friend
139 \fn bool QMqttTopicName::operator!=(const QMqttTopicName &lhs, const QMqttTopicName &rhs)
140
141 Returns \c true if the topic names \a lhs and \a rhs are different,
142 otherwise returns \c false.
143 */
144
145/*!
146 //! friend
147 \fn bool QMqttTopicName::operator<(const QMqttTopicName &lhs, const QMqttTopicName &rhs)
148
149 Returns \c true if the topic name \a lhs is lexically less than the topic
150 name \a rhs; otherwise returns \c false.
151 */
152bool operator<(const QMqttTopicName &lhs, const QMqttTopicName &rhs) Q_DECL_NOTHROW
153{
154 return lhs.d->name < rhs.d->name;
155}
156
157/*!
158 \relates QHash
159
160 Returns the hash value for \a name. If specified, \a seed is used to
161 initialize the hash.
162*/
163size_t qHash(const QMqttTopicName &name, size_t seed) Q_DECL_NOTHROW
164{
165 return qHash(key: name.d->name, seed);
166}
167
168#ifndef QT_NO_DATASTREAM
169/*! \relates QMqttTopicName
170
171 Writes the topic name \a name to the stream \a out and returns a reference
172 to the stream.
173
174 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
175*/
176QDataStream &operator<<(QDataStream &out, const QMqttTopicName &name)
177{
178 out << name.name();
179 return out;
180}
181
182/*! \relates QMqttTopicName
183
184 Reads a topic name into \a name from the stream \a in and returns a
185 reference to the stream.
186
187 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
188*/
189QDataStream &operator>>(QDataStream &in, QMqttTopicName &name)
190{
191 QString n;
192 in >> n;
193 name.setName(n);
194 return in;
195}
196#endif // QT_NO_DATASTREAM
197
198#ifndef QT_NO_DEBUG_STREAM
199QDebug operator<<(QDebug d, const QMqttTopicName &name)
200{
201 QDebugStateSaver saver(d);
202 d.nospace() << "QMqttTopicName(" << name.name() << ')';
203 return d;
204}
205#endif
206
207QT_END_NAMESPACE
208

source code of qtmqtt/src/mqtt/qmqtttopicname.cpp