1/****************************************************************************
2**
3** Copyright (C) 2018 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QCBORSTREAM_H
41#define QCBORSTREAM_H
42
43#include <QtCore/qbytearray.h>
44#include <QtCore/qcborcommon.h>
45#include <QtCore/qfloat16.h>
46#include <QtCore/qscopedpointer.h>
47#include <QtCore/qstring.h>
48#include <QtCore/qstringview.h>
49
50// See qcborcommon.h for why we check
51#if defined(QT_X11_DEFINES_FOUND)
52# undef True
53# undef False
54#endif
55
56QT_BEGIN_NAMESPACE
57
58class QIODevice;
59
60enum class QCborNegativeInteger : quint64 {};
61
62class QCborStreamWriterPrivate;
63class Q_CORE_EXPORT QCborStreamWriter
64{
65public:
66 explicit QCborStreamWriter(QIODevice *device);
67 explicit QCborStreamWriter(QByteArray *data);
68 ~QCborStreamWriter();
69 Q_DISABLE_COPY(QCborStreamWriter)
70
71 void setDevice(QIODevice *device);
72 QIODevice *device() const;
73
74 void append(quint64 u);
75 void append(qint64 i);
76 void append(QCborNegativeInteger n);
77 void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
78 void append(QLatin1String str);
79 void append(QStringView str);
80 void append(QCborTag tag);
81 void append(QCborKnownTags tag) { append(QCborTag(tag)); }
82 void append(QCborSimpleType st);
83 void append(std::nullptr_t) { append(QCborSimpleType::Null); }
84 void append(qfloat16 f);
85 void append(float f);
86 void append(double d);
87
88 void appendByteString(const char *data, qsizetype len);
89 void appendTextString(const char *utf8, qsizetype len);
90
91 // convenience
92 void append(bool b) { append(b ? QCborSimpleType::True : QCborSimpleType::False); }
93 void appendNull() { append(QCborSimpleType::Null); }
94 void appendUndefined() { append(QCborSimpleType::Undefined); }
95
96#ifndef Q_QDOC
97 // overloads to make normal code not complain
98 void append(int i) { append(qint64(i)); }
99 void append(uint u) { append(quint64(u)); }
100#endif
101#ifndef QT_NO_CAST_FROM_ASCII
102 void append(const char *str, qsizetype size = -1)
103 { appendTextString(str, (str && size == -1) ? int(strlen(str)) : size); }
104#endif
105
106 void startArray();
107 void startArray(quint64 count);
108 bool endArray();
109 void startMap();
110 void startMap(quint64 count);
111 bool endMap();
112
113 // no API for encoding chunked strings
114
115private:
116 QScopedPointer<QCborStreamWriterPrivate> d;
117};
118
119class QCborStreamReaderPrivate;
120class Q_CORE_EXPORT QCborStreamReader
121{
122 Q_GADGET
123public:
124 enum Type : quint8 {
125 UnsignedInteger = 0x00,
126 NegativeInteger = 0x20,
127 ByteString = 0x40,
128 ByteArray = ByteString,
129 TextString = 0x60,
130 String = TextString,
131 Array = 0x80,
132 Map = 0xa0,
133 Tag = 0xc0,
134 SimpleType = 0xe0,
135 HalfFloat = 0xf9,
136 Float16 = HalfFloat,
137 Float = 0xfa,
138 Double = 0xfb,
139
140 Invalid = 0xff
141 };
142 Q_ENUM(Type)
143
144 enum StringResultCode {
145 EndOfString = 0,
146 Ok = 1,
147 Error = -1
148 };
149 template <typename Container> struct StringResult {
150 Container data;
151 StringResultCode status = Error;
152 };
153 Q_ENUM(StringResultCode)
154
155 QCborStreamReader();
156 QCborStreamReader(const char *data, qsizetype len);
157 QCborStreamReader(const quint8 *data, qsizetype len);
158 explicit QCborStreamReader(const QByteArray &data);
159 explicit QCborStreamReader(QIODevice *device);
160 ~QCborStreamReader();
161 Q_DISABLE_COPY(QCborStreamReader)
162
163 void setDevice(QIODevice *device);
164 QIODevice *device() const;
165 void addData(const QByteArray &data);
166 void addData(const char *data, qsizetype len);
167 void addData(const quint8 *data, qsizetype len)
168 { addData(reinterpret_cast<const char *>(data), len); }
169 void reparse();
170 void clear();
171 void reset();
172
173 QCborError lastError();
174
175 qint64 currentOffset() const;
176
177 bool isValid() const { return !isInvalid(); }
178
179 int containerDepth() const;
180 QCborStreamReader::Type parentContainerType() const;
181 bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
182 bool next(int maxRecursion = 10000);
183
184 Type type() const { return QCborStreamReader::Type(type_); }
185 bool isUnsignedInteger() const { return type() == UnsignedInteger; }
186 bool isNegativeInteger() const { return type() == NegativeInteger; }
187 bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
188 bool isByteArray() const { return type() == ByteArray; }
189 bool isString() const { return type() == String; }
190 bool isArray() const { return type() == Array; }
191 bool isMap() const { return type() == Map; }
192 bool isTag() const { return type() == Tag; }
193 bool isSimpleType() const { return type() == SimpleType; }
194 bool isFloat16() const { return type() == Float16; }
195 bool isFloat() const { return type() == Float; }
196 bool isDouble() const { return type() == Double; }
197 bool isInvalid() const { return type() == Invalid; }
198
199 bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
200 bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
201 bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
202 bool isBool() const { return isFalse() || isTrue(); }
203 bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
204 bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
205
206 bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
207 quint64 length() const;
208
209 bool isContainer() const { return isMap() || isArray(); }
210 bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
211 bool leaveContainer();
212
213 StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
214 StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
215 qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
216 StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
217
218 bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
219 QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
220 quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
221 QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
222 QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
223 qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
224 float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
225 double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
226
227 qint64 toInteger() const
228 {
229 Q_ASSERT(isInteger());
230 qint64 v = qint64(value64);
231 if (isNegativeInteger())
232 return -v - 1;
233 return v;
234 }
235
236private:
237 void preparse();
238 bool _enterContainer_helper();
239 StringResult<QString> _readString_helper();
240 StringResult<QByteArray> _readByteArray_helper();
241 qsizetype _currentStringChunkSize() const;
242
243 template <typename FP> FP _toFloatingPoint() const noexcept
244 {
245 using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
246 UIntFP u = UIntFP(value64);
247 FP f;
248 memcpy(static_cast<void *>(&f), &u, sizeof(f));
249 return f;
250 }
251
252 friend QCborStreamReaderPrivate;
253 friend class QCborContainerPrivate;
254 quint64 value64;
255 QScopedPointer<QCborStreamReaderPrivate> d;
256 quint8 type_;
257 quint8 reserved[3] = {};
258};
259
260QT_END_NAMESPACE
261
262#if defined(QT_X11_DEFINES_FOUND)
263# define True 1
264# define False 0
265#endif
266
267#endif // QCBORSTREAM_H
268