blob: 7a451e63ac90c23588501efafaac2cb7b657b5f9 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCBORSTREAM_H
#define QCBORSTREAM_H
#include <QtCore/qbytearray.h>
#include <QtCore/qcborcommon.h>
#include <QtCore/qfloat16.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringview.h>
// See qcborcommon.h for why we check
#if defined(QT_X11_DEFINES_FOUND)
# undef True
# undef False
#endif
QT_BEGIN_NAMESPACE
class QIODevice;
enum class QCborNegativeInteger : quint64 {};
class QCborStreamWriterPrivate;
class Q_CORE_EXPORT QCborStreamWriter
{
public:
explicit QCborStreamWriter(QIODevice *device);
explicit QCborStreamWriter(QByteArray *data);
~QCborStreamWriter();
Q_DISABLE_COPY(QCborStreamWriter)
void setDevice(QIODevice *device);
QIODevice *device() const;
void append(quint64 u);
void append(qint64 i);
void append(QCborNegativeInteger n);
void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
void append(QLatin1String str);
void append(QStringView str);
void append(QCborTag tag);
void append(QCborKnownTags tag) { append(QCborTag(tag)); }
void append(QCborSimpleType st);
void append(std::nullptr_t) { append(QCborSimpleType::Null); }
void append(qfloat16 f);
void append(float f);
void append(double d);
void appendByteString(const char *data, qsizetype len);
void appendTextString(const char *utf8, qsizetype len);
// convenience
void append(bool b) { append(b ? QCborSimpleType::True : QCborSimpleType::False); }
void appendNull() { append(QCborSimpleType::Null); }
void appendUndefined() { append(QCborSimpleType::Undefined); }
#ifndef Q_QDOC
// overloads to make normal code not complain
void append(int i) { append(qint64(i)); }
void append(uint u) { append(quint64(u)); }
#endif
#ifndef QT_NO_CAST_FROM_ASCII
void append(const char *str, qsizetype size = -1)
{ appendTextString(str, (str && size == -1) ? int(strlen(str)) : size); }
#endif
void startArray();
void startArray(quint64 count);
bool endArray();
void startMap();
void startMap(quint64 count);
bool endMap();
// no API for encoding chunked strings
private:
QScopedPointer<QCborStreamWriterPrivate> d;
};
class QCborStreamReaderPrivate;
class Q_CORE_EXPORT QCborStreamReader
{
Q_GADGET
public:
enum Type : quint8 {
UnsignedInteger = 0x00,
NegativeInteger = 0x20,
ByteString = 0x40,
ByteArray = ByteString,
TextString = 0x60,
String = TextString,
Array = 0x80,
Map = 0xa0,
Tag = 0xc0,
SimpleType = 0xe0,
HalfFloat = 0xf9,
Float16 = HalfFloat,
Float = 0xfa,
Double = 0xfb,
Invalid = 0xff
};
Q_ENUM(Type)
enum StringResultCode {
EndOfString = 0,
Ok = 1,
Error = -1
};
template <typename Container> struct StringResult {
Container data;
StringResultCode status = Error;
};
Q_ENUM(StringResultCode)
QCborStreamReader();
QCborStreamReader(const char *data, qsizetype len);
QCborStreamReader(const quint8 *data, qsizetype len);
explicit QCborStreamReader(const QByteArray &data);
explicit QCborStreamReader(QIODevice *device);
~QCborStreamReader();
Q_DISABLE_COPY(QCborStreamReader)
void setDevice(QIODevice *device);
QIODevice *device() const;
void addData(const QByteArray &data);
void addData(const char *data, qsizetype len);
void addData(const quint8 *data, qsizetype len)
{ addData(reinterpret_cast<const char *>(data), len); }
void reparse();
void clear();
void reset();
QCborError lastError();
qint64 currentOffset() const;
bool isValid() const { return !isInvalid(); }
int containerDepth() const;
QCborStreamReader::Type parentContainerType() const;
bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
bool next(int maxRecursion = 10000);
Type type() const { return QCborStreamReader::Type(type_); }
bool isUnsignedInteger() const { return type() == UnsignedInteger; }
bool isNegativeInteger() const { return type() == NegativeInteger; }
bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
bool isByteArray() const { return type() == ByteArray; }
bool isString() const { return type() == String; }
bool isArray() const { return type() == Array; }
bool isMap() const { return type() == Map; }
bool isTag() const { return type() == Tag; }
bool isSimpleType() const { return type() == SimpleType; }
bool isFloat16() const { return type() == Float16; }
bool isFloat() const { return type() == Float; }
bool isDouble() const { return type() == Double; }
bool isInvalid() const { return type() == Invalid; }
bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
bool isBool() const { return isFalse() || isTrue(); }
bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
quint64 length() const;
bool isContainer() const { return isMap() || isArray(); }
bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
bool leaveContainer();
StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
qint64 toInteger() const
{
Q_ASSERT(isInteger());
qint64 v = qint64(value64);
if (isNegativeInteger())
return -v - 1;
return v;
}
private:
void preparse();
bool _enterContainer_helper();
StringResult<QString> _readString_helper();
StringResult<QByteArray> _readByteArray_helper();
qsizetype _currentStringChunkSize() const;
template <typename FP> FP _toFloatingPoint() const noexcept
{
using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
UIntFP u = UIntFP(value64);
FP f;
memcpy(static_cast<void *>(&f), &u, sizeof(f));
return f;
}
friend QCborStreamReaderPrivate;
friend class QCborContainerPrivate;
quint64 value64;
QScopedPointer<QCborStreamReaderPrivate> d;
quint8 type_;
quint8 reserved[3] = {};
};
QT_END_NAMESPACE
#if defined(QT_X11_DEFINES_FOUND)
# define True 1
# define False 0
#endif
#endif // QCBORSTREAM_H