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 QCBORSTREAMREADER_H
41 #define QCBORSTREAMREADER_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 QT_REQUIRE_CONFIG(cborstreamreader);
51 
52 // See qcborcommon.h for why we check
53 #if defined(QT_X11_DEFINES_FOUND)
54 #  undef True
55 #  undef False
56 #endif
57 
58 QT_BEGIN_NAMESPACE
59 
60 class QIODevice;
61 
62 class QCborStreamReaderPrivate;
63 class Q_CORE_EXPORT QCborStreamReader
64 {
65     Q_GADGET
66 public:
67     enum Type : quint8 {
68         UnsignedInteger     = 0x00,
69         NegativeInteger     = 0x20,
70         ByteString          = 0x40,
71         ByteArray           = ByteString,
72         TextString          = 0x60,
73         String              = TextString,
74         Array               = 0x80,
75         Map                 = 0xa0,
76         Tag                 = 0xc0,
77         SimpleType          = 0xe0,
78         HalfFloat           = 0xf9,
79         Float16             = HalfFloat,
80         Float               = 0xfa,
81         Double              = 0xfb,
82 
83         Invalid             = 0xff
84     };
85     Q_ENUM(Type)
86 
87     enum StringResultCode {
88         EndOfString = 0,
89         Ok = 1,
90         Error = -1
91     };
92     template <typename Container> struct StringResult {
93         Container data;
94         StringResultCode status = Error;
95     };
96     Q_ENUM(StringResultCode)
97 
98     QCborStreamReader();
99     QCborStreamReader(const char *data, qsizetype len);
100     QCborStreamReader(const quint8 *data, qsizetype len);
101     explicit QCborStreamReader(const QByteArray &data);
102     explicit QCborStreamReader(QIODevice *device);
103     ~QCborStreamReader();
104     Q_DISABLE_COPY(QCborStreamReader)
105 
106     void setDevice(QIODevice *device);
107     QIODevice *device() const;
108     void addData(const QByteArray &data);
109     void addData(const char *data, qsizetype len);
addData(const quint8 * data,qsizetype len)110     void addData(const quint8 *data, qsizetype len)
111     { addData(reinterpret_cast<const char *>(data), len); }
112     void reparse();
113     void clear();
114     void reset();
115 
116     QCborError lastError();
117 
118     qint64 currentOffset() const;
119 
isValid()120     bool isValid() const        { return !isInvalid(); }
121 
122     int containerDepth() const;
123     QCborStreamReader::Type parentContainerType() const;
124     bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
125     bool next(int maxRecursion = 10000);
126 
type()127     Type type() const               { return QCborStreamReader::Type(type_); }
isUnsignedInteger()128     bool isUnsignedInteger() const  { return type() == UnsignedInteger; }
isNegativeInteger()129     bool isNegativeInteger() const  { return type() == NegativeInteger; }
isInteger()130     bool isInteger() const          { return quint8(type()) <= quint8(NegativeInteger); }
isByteArray()131     bool isByteArray() const        { return type() == ByteArray; }
isString()132     bool isString() const           { return type() == String; }
isArray()133     bool isArray() const            { return type() == Array; }
isMap()134     bool isMap() const              { return type() == Map; }
isTag()135     bool isTag() const              { return type() == Tag; }
isSimpleType()136     bool isSimpleType() const       { return type() == SimpleType; }
isFloat16()137     bool isFloat16() const          { return type() == Float16; }
isFloat()138     bool isFloat() const            { return type() == Float; }
isDouble()139     bool isDouble() const           { return type() == Double; }
isInvalid()140     bool isInvalid() const          { return type() == Invalid; }
141 
isSimpleType(QCborSimpleType st)142     bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
isFalse()143     bool isFalse() const            { return isSimpleType(QCborSimpleType::False); }
isTrue()144     bool isTrue() const             { return isSimpleType(QCborSimpleType::True); }
isBool()145     bool isBool() const             { return isFalse() || isTrue(); }
isNull()146     bool isNull() const             { return isSimpleType(QCborSimpleType::Null); }
isUndefined()147     bool isUndefined() const        { return isSimpleType(QCborSimpleType::Undefined); }
148 
149     bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
150     quint64 length() const;
151 
isContainer()152     bool isContainer() const            { return isMap() || isArray(); }
enterContainer()153     bool enterContainer()               { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
154     bool leaveContainer();
155 
readString()156     StringResult<QString> readString()      { Q_ASSERT(isString()); return _readString_helper(); }
readByteArray()157     StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
currentStringChunkSize()158     qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
159     StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
160 
toBool()161     bool toBool() const                 { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
toTag()162     QCborTag toTag() const              { Q_ASSERT(isTag()); return QCborTag(value64); }
toUnsignedInteger()163     quint64 toUnsignedInteger() const   { Q_ASSERT(isUnsignedInteger()); return value64; }
toNegativeInteger()164     QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
toSimpleType()165     QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
toFloat16()166     qfloat16 toFloat16() const          { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
toFloat()167     float toFloat() const               { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
toDouble()168     double toDouble() const             { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
169 
toInteger()170     qint64 toInteger() const
171     {
172         Q_ASSERT(isInteger());
173         qint64 v = qint64(value64);
174         if (isNegativeInteger())
175             return -v - 1;
176         return v;
177     }
178 
179 private:
180     void preparse();
181     bool _enterContainer_helper();
182     StringResult<QString> _readString_helper();
183     StringResult<QByteArray> _readByteArray_helper();
184     qsizetype _currentStringChunkSize() const;
185 
_toFloatingPoint()186     template <typename FP> FP _toFloatingPoint() const noexcept
187     {
188         using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
189         UIntFP u = UIntFP(value64);
190         FP f;
191         memcpy(static_cast<void *>(&f), &u, sizeof(f));
192         return f;
193     }
194 
195     friend QCborStreamReaderPrivate;
196     friend class QCborContainerPrivate;
197     quint64 value64;
198     QScopedPointer<QCborStreamReaderPrivate> d;
199     quint8 type_;
200     quint8 reserved[3] = {};
201 };
202 
203 QT_END_NAMESPACE
204 
205 #if defined(QT_X11_DEFINES_FOUND)
206 #  define True  1
207 #  define False 0
208 #endif
209 
210 #endif // QCBORSTREAMREADER_H
211