1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
5#include "qndefrecord.h"
6#include "qndefrecord_p.h"
7
8#include <QtCore/QHash>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \class QNdefRecord
14 \brief The QNdefRecord class provides an NFC NDEF record.
15
16 \ingroup connectivity-nfc
17 \inmodule QtNfc
18 \since 5.2
19
20 QNdefRecord and derived classes are used to parse the contents of
21 \l {QNdefMessage}{NDEF messages} and create new NDEF messages.
22
23 Use typeNameFormat() and setTypeNameFormat() to
24 get and set the type name format of the NDEF record.
25
26 Use type() and setType() to get and set the type of the NDEF record.
27
28 Use id() and setId() to get and set the id of the NDEF record.
29
30 Use payload() and setPayload() to get and set the NDEF record payload. isEmpty() can be used
31 to test if the payload is empty.
32
33 QNdefRecord is an implicitly shared class. This means you can efficiently convert between
34 QNdefRecord and specialized record classes. The isRecordType() template function can be used
35 to test if a conversion is possible. The following example shows how to test if a QNdefRecord
36 is an NFC RTD Text record and extract the text information from it.
37
38 \snippet nfc.cpp Record conversion
39
40 \section1 Creating Specialized NDEF Record Classes
41
42 Specialized NDEF record classes can be easily created with the Q_DECLARE_NDEF_RECORD() and
43 Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD() macros. The following example shows the class
44 declaration of the hypothetical \e {example.com:f} record type that encapsulates a single int
45 property foo.
46
47 \snippet nfc.cpp Specialized class definition
48
49 The developer only needs to provide implementations for the \c {foo()} and \c {setFoo()}
50 functions that parse and set the contents of the NDEF record's payload.
51*/
52
53/*!
54 \enum QNdefRecord::TypeNameFormat
55
56 This enum describes the type name format of an NDEF record.
57
58 \value Empty An empty NDEF record, the record does not contain a payload
59 \value NfcRtd The NDEF record type is defined by an NFC RTD Specification
60 \value Mime The NDEF record type follows the construct described in RFC 2046
61 \value Uri The NDEF record type follows the construct described in RFC 3986
62 \value ExternalRtd The NDEF record type follows the construct for external type names
63 described the NFC RTD Specification
64 \value Unknown The type of the record is unknown and should be treated similar to content
65 with MIME type 'application/octet-stream' without further context
66*/
67
68/*!
69 \fn bool QNdefRecord::isRecordType() const
70
71 Returns \c true if the NDEF record is of the specified record type;
72 otherwise returns \c false.
73*/
74
75/*!
76 \fn bool QNdefRecord::operator!=(const QNdefRecord &other) const
77
78 Returns \c true if this NDEF record does not equal \a other;
79 otherwise return \c false.
80*/
81
82/*!
83 \macro Q_DECLARE_NDEF_RECORD(className, typeNameFormat, type, initialPayload)
84 \relates QNdefRecord
85
86 This macro declares default and copy constructors for specialized NDEF record classes.
87
88 \a className is the name of the specialized class, \a typeNameFormat is the appropriate
89 QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS
90 prefixes. That is \e {example.com:f} not \e {urn:nfc:ext:example.com:f}. \a initialPayload
91 is the initial payload of an empty record, it must be a QByteArray or a type that can be
92 implicitly converted into a QByteArray.
93
94 See the section on \l {Creating specialized NDEF record classes} for details.
95
96 \sa Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD()
97*/
98
99/*!
100 \macro Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(className, typeNameFormat, type)
101 \relates QNdefRecord
102
103 This macro declares a template specialization for the QNdefRecord::isRecordType() function.
104
105 This macro should be used in the header file directly after the definition of a specialized
106 NDEF record class.
107
108 \a className is the name of the specialized class, \a typeNameFormat is the appropriate
109 QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS
110 prefixes. That is \e {example.com:f} not \e {urn:nfc:ext:example.com:f}.
111
112 See the section on \l {Creating specialized NDEF record classes} for details.
113
114 \sa Q_DECLARE_NDEF_RECORD()
115*/
116
117size_t qHash(const QNdefRecord &key)
118{
119 return qHash(key: key.type() + key.id() + key.payload());
120}
121
122/*!
123 Constructs a new empty NDEF record.
124*/
125QNdefRecord::QNdefRecord()
126{
127}
128
129/*!
130 Constructs a new NDEF record that is a copy of \a other.
131*/
132QNdefRecord::QNdefRecord(const QNdefRecord &other)
133{
134 d = other.d;
135}
136
137/*!
138 \internal
139
140 Constructs an NDEF record that is a copy of \a other if \a other is of the expected type name
141 format identified by \a typeNameFormat and type as identified by \a type; otherwise an empty
142 NDEF record of the expected type name format and type is created.
143*/
144QNdefRecord::QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat,
145 const QByteArray &type)
146{
147 if (other.d->typeNameFormat == quint8(typeNameFormat) && other.d->type == type) {
148 d = other.d;
149 } else {
150 d = new QNdefRecordPrivate;
151 d->typeNameFormat = typeNameFormat;
152 d->type = type;
153 }
154}
155
156/*!
157 \internal
158
159 Constructs an NDEF record that is a copy of \a other if \a other is of the expected type name
160 format identified by \a typeNameFormat; otherwise an empty NDEF record of the expected type
161 name format and type is created.
162*/
163QNdefRecord::QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat)
164{
165 if (other.d->typeNameFormat == quint8(typeNameFormat)) {
166 d = other.d;
167 } else {
168 d = new QNdefRecordPrivate;
169 d->typeNameFormat = typeNameFormat;
170 }
171}
172
173/*!
174 \internal
175
176 Constructs an NDEF record with a type name format identified by \a typeNameFormat and type as
177 identified by \a type.
178*/
179QNdefRecord::QNdefRecord(TypeNameFormat typeNameFormat, const QByteArray &type)
180: d(new QNdefRecordPrivate)
181{
182 d->typeNameFormat = typeNameFormat;
183 d->type = type;
184}
185
186/*!
187 Destroys the NDEF record.
188*/
189QNdefRecord::~QNdefRecord()
190{
191}
192
193/*!
194 Assigns this NDEF record to \a other.
195*/
196QNdefRecord &QNdefRecord::operator=(const QNdefRecord &other)
197{
198 if (this != &other)
199 d = other.d;
200
201 return *this;
202}
203
204/*!
205 Sets the type name format of the NDEF record to \a typeNameFormat.
206*/
207void QNdefRecord::setTypeNameFormat(TypeNameFormat typeNameFormat)
208{
209 if (!d)
210 d = new QNdefRecordPrivate;
211
212 d->typeNameFormat = typeNameFormat;
213}
214
215/*!
216 Returns the type name format of the NDEF record.
217*/
218QNdefRecord::TypeNameFormat QNdefRecord::typeNameFormat() const
219{
220 if (!d)
221 return Empty;
222
223 if (d->typeNameFormat > 0x05)
224 return Unknown;
225
226 return TypeNameFormat(d->typeNameFormat);
227}
228
229/*!
230 Sets the type of the NDEF record to \a type.
231*/
232void QNdefRecord::setType(const QByteArray &type)
233{
234 if (!d)
235 d = new QNdefRecordPrivate;
236
237 d->type = type;
238}
239
240/*!
241 Returns the type of the NDEF record.
242*/
243QByteArray QNdefRecord::type() const
244{
245 if (!d)
246 return QByteArray();
247
248 return d->type;
249}
250
251/*!
252 Sets the id of the NDEF record to \a id.
253*/
254void QNdefRecord::setId(const QByteArray &id)
255{
256 if (!d)
257 d = new QNdefRecordPrivate;
258
259 d->id = id;
260}
261
262/*!
263 Returns the id of the NDEF record.
264*/
265QByteArray QNdefRecord::id() const
266{
267 if (!d)
268 return QByteArray();
269
270 return d->id;
271}
272
273/*!
274 Sets the payload of the NDEF record to \a payload.
275*/
276void QNdefRecord::setPayload(const QByteArray &payload)
277{
278 if (!d)
279 d = new QNdefRecordPrivate;
280
281 d->payload = payload;
282}
283
284/*!
285 Returns the payload of the NDEF record.
286*/
287QByteArray QNdefRecord::payload() const
288{
289 if (!d)
290 return QByteArray();
291
292 return d->payload;
293}
294
295/*!
296 Returns \c true if the NDEF record contains an empty payload;
297 otherwise returns \c false.
298
299 This is equivalent to calling \c {payload().isEmpty()}.
300*/
301bool QNdefRecord::isEmpty() const
302{
303 if (!d)
304 return true;
305
306 return d->payload.isEmpty();
307}
308
309/*!
310 Returns \c true if \a other and this NDEF record are the same.
311 Otherwise returns \c false.
312*/
313bool QNdefRecord::operator==(const QNdefRecord &other) const
314{
315 if (d == other.d)
316 return true;
317
318 if (!d || !other.d)
319 return false;
320
321 if (d->typeNameFormat != other.d->typeNameFormat)
322 return false;
323
324 if (d->type != other.d->type)
325 return false;
326
327 if (d->id != other.d->id)
328 return false;
329
330 if (d->payload != other.d->payload)
331 return false;
332
333 return true;
334}
335
336/*!
337 \since 6.2
338
339 Clear the NDEF record.
340
341 An \l isEmpty() call returns \c true for a cleared record. The record
342 \l type() is set to \l {QNdefRecord::}{Empty}.
343*/
344void QNdefRecord::clear()
345{
346 if (d) {
347 d->typeNameFormat = 0;
348 d->type.clear();
349 d->id.clear();
350 d->payload.clear();
351 }
352}
353
354QT_END_NAMESPACE
355

source code of qtconnectivity/src/nfc/qndefrecord.cpp