Commit c9c381b8 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

File forgotten in previous commit + Qt _impl.h convention

parent f2a12e70
......@@ -27,6 +27,6 @@ SOURCES += \
main.cpp
HEADERS += \
QCborWriter.hpp \
QJson.hpp \
QBind.hpp
QBind_impl.h \
QCbor_impl.h \
QJson_impl.h
/****************************************************************************
* **
* ** Copyright (C) 2017 MinMaxMedical.
* ** All rights reserved.
* ** Contact: MinMaxMedical <InCAS@MinMaxMedical.com>
* **
* ** This file is part of the modmedLog module.
* **
* ** $QT_BEGIN_LICENSE:BSD$
* ** You may use this file under the terms of the BSD license as follows:
* **
* ** "Redistribution and use in source and binary forms, with or without
* ** modification, are permitted provided that the following conditions are
* ** met:
* ** * Redistributions of source code must retain the above copyright
* ** notice, this list of conditions and the following disclaimer.
* ** * Redistributions in binary form must reproduce the above copyright
* ** notice, this list of conditions and the following disclaimer in
* ** the documentation and/or other materials provided with the
* ** distribution.
* ** * Neither the name of MinMaxMedical S.A.S. and its Subsidiary(-ies) nor
* ** the names of its contributors may be used to endorse or promote
* ** products derived from this software without specific prior written
* ** permission.
* **
* ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
* ** $QT_END_LICENSE$
* **
* ****************************************************************************/
#pragma once
#include <type_traits>
#include <QtCore/qiodevice.h>
#include <QtCore/qendian.h>
#include "QBind.hpp"
namespace cbor {
//! CBOR Major types
//! Encoded in the high 3 bits of the descriptor byte
//! \see http://tools.ietf.org/html/rfc7049#section-2.1
enum MajorTypes {
TextStringType = 3,
ArrayType = 4,
SimpleTypesType = 7
};
//! CBOR simple and floating point types
//! Encoded in the low 5 bits of the descriptor byte when the Major Type is 7.
enum SimpleTypes {
NullValue = 22,
SinglePrecisionFloat = 26,
DoublePrecisionFloat = 27,
Break = 31
};
enum {
SmallValueBitLength = 5U,
Value8Bit = 24U,
Value16Bit = 25U,
Value32Bit = 26U,
Value64Bit = 27U,
IndefiniteLength = 31U,
MajorTypeShift = SmallValueBitLength,
};
enum : unsigned char {
BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift),
IndefiniteLengthArrayByte = IndefiniteLength | (ArrayType << MajorTypeShift),
NullByte = NullValue | (SimpleTypesType << MajorTypeShift)
};
enum tag{
Tag = 192,
DateTime = 0,
CborDocument = 55799,
};
} // cbor
// //////////////////////////////////////////////////////////////////////////
// QBind<QCborWriter,T> support
class QCborWriterImpl;
class QCborWriter : public QScopedResult<QCborWriter, QCborWriterImpl, BindMode::Write>
{
Q_DISABLE_COPY(QCborWriter) // but not swap
public:
Q_ENABLE_DEFAULT_MOVE(QCborWriter)
QCborWriter(QIODevice* io);
private:
friend class QCborWriterImpl; // uses method below
QCborWriter(QCborWriterImpl* outer) : QScopedResult(outer, false) {}
};
class QCborWriterImpl
{
QIODevice* io;
int levels = 0; //!< minimal dynamic context to ensure well-formedness in case TResult is abandoned
public:
QCborWriterImpl() = default;
QCborWriterImpl(QIODevice* io) : io(io) { Q_ASSERT(io); }
~QCborWriterImpl() { while (levels) out(); }
protected:
template<class T_> friend class Val; // calls methods below
bool sequence() { levels++;
io->putChar(cbor::IndefiniteLengthArrayByte);
return true; }
bool null() { io->putChar(cbor::NullByte);
return true; }
bool bind(const char* s) { putInteger (cbor::TextStringType, strlen(s));
io->write(s);
return true; }
// Natively supported overloads
bool bind( float n) { io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::SinglePrecisionFloat);
union { float value; quint32 bits; } number;
number.value = n;
char bytes[sizeof(number.bits)];
qToBigEndian(number.bits, bytes);
io->write(bytes, sizeof(bytes));
return true; }
bool bind( double n) { io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::DoublePrecisionFloat);
union { double value; quint64 bits; } number;
number.value = n;
char bytes[sizeof(number.bits)];
qToBigEndian(number.bits, bytes);
io->write(bytes, sizeof(bytes));
return true; }
// Val<TResult> prevents QBind from getting out() of an outer Seq for instance
template<typename T> bool bind(const T& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), const_cast<T&>(t)); } // t will not be modified anyway
template<typename T> bool bind( T& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), t ); }
template<typename T> bool bind( T&& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), t ); }
template<class T_> friend class Seq; // calls methods below
bool item() { return true; }
bool out() { io->putChar(cbor::BreakByte); levels--; return true; }
private:
void putInteger(char majorType, quint64 n)
{
// See https://tools.ietf.org/html/rfc7049#section-2.2 if more performance is needed
if (n < 24) {
io->putChar((majorType << cbor::MajorTypeShift) | n);
} else {
char bytes[8];
if (n <= 0xff ) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value8Bit ); qToBigEndian(quint8 (n),bytes); io->write(bytes,sizeof(quint8 )); }
else if (n <= 0xffff ) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value16Bit); qToBigEndian(quint16(n),bytes); io->write(bytes,sizeof(quint16)); }
else if (n <= 0xffffffffL) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value32Bit); qToBigEndian(quint32(n),bytes); io->write(bytes,sizeof(quint32)); }
else { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value64Bit); qToBigEndian( n ,bytes); io->write(bytes,sizeof(quint64)); }
}
}
};
QCborWriter::QCborWriter(QIODevice* io) : QScopedResult(new QCborWriterImpl(io), true) {}
/****************************************************************************
* **
* ** Copyright (C) 2017 MinMaxMedical.
* ** All rights reserved.
* ** Contact: MinMaxMedical <InCAS@MinMaxMedical.com>
* **
* ** This file is part of the modmedLog module.
* **
* ** $QT_BEGIN_LICENSE:BSD$
* ** You may use this file under the terms of the BSD license as follows:
* **
* ** "Redistribution and use in source and binary forms, with or without
* ** modification, are permitted provided that the following conditions are
* ** met:
* ** * Redistributions of source code must retain the above copyright
* ** notice, this list of conditions and the following disclaimer.
* ** * Redistributions in binary form must reproduce the above copyright
* ** notice, this list of conditions and the following disclaimer in
* ** the documentation and/or other materials provided with the
* ** distribution.
* ** * Neither the name of MinMaxMedical S.A.S. and its Subsidiary(-ies) nor
* ** the names of its contributors may be used to endorse or promote
* ** products derived from this software without specific prior written
* ** permission.
* **
* ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
* ** $QT_END_LICENSE$
* **
* ****************************************************************************/
#pragma once
#include <type_traits>
#include <QtCore/qiodevice.h>
#include <QtCore/qendian.h>
#include "QBind_impl.h"
namespace cbor {
//! CBOR Major types
//! Encoded in the high 3 bits of the descriptor byte
//! \see http://tools.ietf.org/html/rfc7049#section-2.1
enum MajorTypes {
TextStringType = 3,
ArrayType = 4,
SimpleTypesType = 7
};
//! CBOR simple and floating point types
//! Encoded in the low 5 bits of the descriptor byte when the Major Type is 7.
enum SimpleTypes {
NullValue = 22,
SinglePrecisionFloat = 26,
DoublePrecisionFloat = 27,
Break = 31
};
enum {
SmallValueBitLength = 5U,
Value8Bit = 24U,
Value16Bit = 25U,
Value32Bit = 26U,
Value64Bit = 27U,
IndefiniteLength = 31U,
MajorTypeShift = SmallValueBitLength,
};
enum : unsigned char {
BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift),
IndefiniteLengthArrayByte = IndefiniteLength | (ArrayType << MajorTypeShift),
NullByte = NullValue | (SimpleTypesType << MajorTypeShift)
};
enum tag{
Tag = 192,
DateTime = 0,
CborDocument = 55799,
};
} // cbor
// //////////////////////////////////////////////////////////////////////////
// QBind<QCborWriter,T> support
class QCborWriterImpl;
class QCborWriter : public QScopedResult<QCborWriter, QCborWriterImpl, BindMode::Write>
{
Q_DISABLE_COPY(QCborWriter) // but not swap
public:
Q_ENABLE_MOVE_DEFAULT(QCborWriter)
QCborWriter(QIODevice* io);
private:
friend class QCborWriterImpl; // uses method below
QCborWriter(QCborWriterImpl* outer) : QScopedResult(outer, false) {}
};
class QCborWriterImpl
{
QIODevice* io;
int levels = 0; //!< minimal dynamic context to ensure well-formedness in case TResult is abandoned
public:
QCborWriterImpl() = default;
QCborWriterImpl(QIODevice* io) : io(io) { Q_ASSERT(io); }
~QCborWriterImpl() { while (levels) out(); }
protected:
template<class T_> friend class Val; // calls methods below
bool sequence() { levels++;
io->putChar(cbor::IndefiniteLengthArrayByte);
return true; }
bool null() { io->putChar(cbor::NullByte);
return true; }
bool bind(const char* s) { putInteger (cbor::TextStringType, strlen(s));
io->write(s);
return true; }
// Natively supported overloads
bool bind( float n) { io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::SinglePrecisionFloat);
union { float value; quint32 bits; } number;
number.value = n;
char bytes[sizeof(number.bits)];
qToBigEndian(number.bits, bytes);
io->write(bytes, sizeof(bytes));
return true; }
bool bind( double n) { io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::DoublePrecisionFloat);
union { double value; quint64 bits; } number;
number.value = n;
char bytes[sizeof(number.bits)];
qToBigEndian(number.bits, bytes);
io->write(bytes, sizeof(bytes));
return true; }
// Val<TResult> prevents QBind from getting out() of an outer Seq for instance
template<typename T> bool bind(const T& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), const_cast<T&>(t)); } // t will not be modified anyway
template<typename T> bool bind( T& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), t ); }
template<typename T> bool bind( T&& t) { return QBind<QCborWriter,T>::bind(QCborWriter(this).value(), t ); }
template<class T_> friend class Seq; // calls methods below
bool item() { return true; }
bool out() { io->putChar(cbor::BreakByte); levels--; return true; }
private:
void putInteger(char majorType, quint64 n)
{
// See https://tools.ietf.org/html/rfc7049#section-2.2 if more performance is needed
if (n < 24) {
io->putChar((majorType << cbor::MajorTypeShift) | n);
} else {
char bytes[8];
if (n <= 0xff ) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value8Bit ); qToBigEndian(quint8 (n),bytes); io->write(bytes,sizeof(quint8 )); }
else if (n <= 0xffff ) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value16Bit); qToBigEndian(quint16(n),bytes); io->write(bytes,sizeof(quint16)); }
else if (n <= 0xffffffffL) { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value32Bit); qToBigEndian(quint32(n),bytes); io->write(bytes,sizeof(quint32)); }
else { io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value64Bit); qToBigEndian( n ,bytes); io->write(bytes,sizeof(quint64)); }
}
}
};
QCborWriter::QCborWriter(QIODevice* io) : QScopedResult(new QCborWriterImpl(io), true) {}
......@@ -42,12 +42,12 @@
// - a fluent interface for describing logical data structures, providing auto completion and well-formedness guarantees
// - a set of recursive QBind<TResult,T> functors binding TResult and T according to their logical data structure
#include "QBind.hpp"
#include "QBind_impl.h"
// Extensible set of TResult implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
#include "QJson.hpp" // QJsonWriter, QJsonReader, QJsonBuilder and QBind<_,QJsonValue> support
#include "QCborWriter.hpp" // QCborWriter demonstrating the performance potential of the approach
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder and QBind<_,QJsonValue> support
#include "QCbor_impl.h" // QCborWriter demonstrating the performance potential of the approach
// //////////////////////////////////////////////////////////////////////////
// QBind<_,T> basic example using an internal bind<TResult> method
......@@ -74,16 +74,14 @@ struct Person
#include <type_traits>
#include <QtCore/qiodevice.h>
class TextWriter;
class TextWriterImpl
class TextWriter : public QMovedResult<TextWriter, BindMode::Write>
{
// for QScopedResult only Q_DISABLE_COPY(TextWriterImpl)
Q_DISABLE_COPY(TextWriter)
public:
TextWriterImpl(const TextWriterImpl&) = default; // for QMovedResult only
Q_ENABLE_DEFAULT_MOVE(TextWriterImpl) // for QMovedResult only
operator bool() { return io; } // for QMovedResult only
Q_ENABLE_MOVE_DEFAULT(TextWriter)
TextWriter(QIODevice* io) : io(io) { Q_ASSERT(io); }
TextWriterImpl(QIODevice* io) : io(io) { Q_ASSERT(io); }
operator bool() { return io; }
protected:
template<class T_> friend class Val; // enables calling methods below through operator->()
......@@ -92,9 +90,9 @@ protected:
bool bind(const char* s) { io->write( s ); return true; }
// Val<TResult> prevents QBind from getting out() of an outer Seq for instance
template<typename T> bool bind(const T& t);
template<typename T> bool bind( T& t);
template<typename T> bool bind( T&& t);
template<typename T> bool bind(const T& t) { return QBind<TResult,T>::bind(Val<TResult>(TResult(io)), const_cast<T&>(t)); } // t will not be modified anyway
template<typename T> bool bind( T& t) { return QBind<TResult,T>::bind(Val<TResult>(TResult(io)), t ); }
template<typename T> bool bind( T&& t) { return QBind<TResult,T>::bind(Val<TResult>(TResult(io)), t ); }
template<class T_> friend class Seq; // enables calling methods below through operator->()
......@@ -103,20 +101,6 @@ protected:
private:
QIODevice* io = nullptr;
};
class TextWriter : public QMovedResult<TextWriter, TextWriterImpl, BindMode::Write>
{
Q_DISABLE_COPY(TextWriter)
public:
Q_ENABLE_DEFAULT_MOVE(TextWriter)
TextWriter(QIODevice* io) : QMovedResult(std::move(TextWriterImpl(io))) {} // QScopedResult(new TextWriterImpl(io), true) {}
private:
friend class TextWriterImpl; // uses method below
TextWriter(const TextWriterImpl& outer) : QMovedResult(outer) {} // QScopedResult(outer, false) {}
};
template<typename T> bool TextWriterImpl::bind(const T& t) { return QBind<TextWriter,T>::bind(TextWriter(std::move(*this)).value(), const_cast<T&>(t)); } // t will not be modified anyway
template<typename T> bool TextWriterImpl::bind( T& t) { return QBind<TextWriter,T>::bind(TextWriter(std::move(*this)).value(), t ); }
template<typename T> bool TextWriterImpl::bind( T&& t) { return QBind<TextWriter,T>::bind(TextWriter(std::move(*this)).value(), t ); }
// //////////////////////////////////////////////////////////////////////////
// Tests and Benchmarks
......@@ -193,11 +177,11 @@ int main()
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b)
TextWriter(&b).value()
.sequence()
.bind(123)
.bind(text)
.result(); // automatically closes opened sequence
;
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
......@@ -245,7 +229,7 @@ int main()
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b).bind(transform);
TextWriter(&b).value().bind(transform);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
......@@ -284,7 +268,7 @@ int main()
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b).bind(person);
TextWriter(&b).value().bind(person);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment