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

Added QDataStream bench out of curiosity

parent de976e62
......@@ -31,4 +31,5 @@ SOURCES += \
HEADERS += \
QBind_impl.h \
QCbor_impl.h \
QJson_impl.h
QJson_impl.h \
QDataStream_impl.h
......@@ -119,7 +119,7 @@ protected:
bool _sequence() { levels++; return io->putChar(cbor::IndefiniteLengthArrayByte) ; }
bool _bind(const char* s) { return (putInteger(cbor::TextStringType, strlen(s)) && io->write(s)); }
// Natively supported overloads
// BindNative overloads
bool _bind( bool& b) { return io->putChar(b ? cbor::TrueByte : cbor::FalseByte); }
bool _bind( float& n) { union { float value; quint32 bits; } number = { n };
char bytes[sizeof(number.bits)]; qToBigEndian(number.bits, bytes);
......
/****************************************************************************
* **
* ** Copyright (C) 2018 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/qdatastream.h>
#include <QtCore/qstack.h>
#include "QBind_impl.h"
enum DataTag : quint8 { Unknown = 0x00, Null = 0xBB, Record = 0xCC, Sequence = 0xDD, Item = 0xEE, Out = 0xFF };
// //////////////////////////////////////////////////////////////////////////
// QBind<QDataStream*,T> support
class DataStreamWriter : public QMovedWriter<DataStreamWriter>
{
protected:
DataStreamWriter(const DataStreamWriter &o) : QMovedWriter(), io(o.io) {}
DataStreamWriter &operator=(const DataStreamWriter &) = delete;
public:
Q_ENABLE_MOVE(DataStreamWriter, std::swap(io, o.io); )
DataStreamWriter(QDataStream* io) : io(io) { Q_ASSERT(io); }
operator bool() { return io->status()==QDataStream::Ok; } // for QMovedWriter
protected:
friend class QMovedWriter<DataStreamWriter>;
template<class T_> friend class Val; // calls methods below
bool _sequence() { *io << Sequence; return true; }
bool _null() { *io << Null ; return true; }
bool _bind(const char* s) { *io << s ; return true; }
// Natively supported overloads
bool _bind( bool& b) { *io << b ; return true; }
bool _bind( float& f) { *io << f ; return true; }
bool _bind( double& d) { *io << d ; return true; }
// This dispatch would be more simple with C++17 constexpr if
template<typename T> bool _bind(T t, typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type* =nullptr) { *io << qulonglong(t); return true; }
template<typename T> bool _bind(T t, typename std::enable_if<std::is_integral<T>::value && std:: is_signed<T>::value>::type* =nullptr) { *io << qlonglong(t); return true; }
template<class T_> friend class Seq; // calls methods below
bool _item() { *io << Item; return true; }
bool _out() { *io << Out ; return true; }
private:
QDataStream* io;
};
template<> struct BindSupport<DataStreamWriter,const char*> : BindNative {};
template<> struct BindSupport<DataStreamWriter, bool&> : BindNative {};
template<> struct BindSupport<DataStreamWriter, float&> : BindNative {};
template<> struct BindSupport<DataStreamWriter, double&> : BindNative {};
template<typename T> struct BindSupport<DataStreamWriter,T&,typename std::enable_if<std::is_integral<T>::value>::type> : BindNative {};
// --------------------------------------------------------------------------
class QDataStreamReaderImpl;
class QDataStreamReader : public QScopedResult<QDataStreamReader, QDataStreamReaderImpl, BindMode::Read>
{
Q_PROTECTED_COPY(QDataStreamReader)
public:
Q_ENABLE_MOVE_DEFAULT(QDataStreamReader)
QDataStreamReader(QIODevice *io);
private:
friend class QScopedResult<QDataStreamReader, QDataStreamReaderImpl, BindMode::Read>;
friend class QDataStreamReaderImpl; // uses method below
QDataStreamReader(QDataStreamReaderImpl* outer) : QScopedResult(outer, false) {}
};
class QDataStreamReaderImpl
{
Q_DISABLE_COPY(QDataStreamReaderImpl)
QDataStream io;
int levels = 0; //!< dynamic context required to implement item()
quint8 nextTag = Unknown;
public:
QDataStreamReaderImpl(QIODevice* io) : io(io) { Q_ASSERT(io); }
protected:
friend class ScopedChoice<Val<QDataStreamReader>>;
void setChoice(bool) { /* not implemented */ }
friend class QScopedResult<QDataStreamReader, QDataStreamReaderImpl, BindMode::Read>;
void reportError(const char*) { /* not implemented */ }
template<class T_> friend class Val; // calls methods below
bool _sequence() { if (get(Sequence)) { levels++; return true; } else return false; }
bool _null() { return get(Null); }
bool _bind(QByteArray& s) { io >> s; return true; }
// BindNative overloads
bool _bind( bool& b) { io >> b; return true; }
bool _bind( float& f) { io >> f; return true; }
bool _bind( double& d) { io >> d; return true; }
template<typename T> bool _bind(T& t, typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type* =nullptr) { io >> t; return true; }
template<typename T> bool _bind(T& t, typename std::enable_if<std::is_integral<T>::value && std:: is_signed<T>::value>::type* =nullptr) { io >> t; return true; }
bool _bind() { Q_ASSERT_X(false,Q_FUNC_INFO,"Cannot Read unknown type"); return false; }
template<class T_> friend class Seq; // calls methods below
bool _item() { return get(Item); }
bool _out() { if (get(Out)) { levels--; return true; } else return false; }
private:
bool get(DataTag expected) {
if (nextTag==Unknown) {
io >> nextTag;
}
if (nextTag==expected) {
nextTag= Unknown;
return true;
}
return false;
}
};
QDataStreamReader::QDataStreamReader(QIODevice* io) : QScopedResult(new QDataStreamReaderImpl(io), true) {}
template<> struct BindSupport<QDataStreamReaderImpl, void> : BindNative {};
template<> struct BindSupport<QDataStreamReaderImpl,QByteArray&> : BindNative {};
template<> struct BindSupport<QDataStreamReaderImpl, bool&> : BindNative {};
template<> struct BindSupport<QDataStreamReaderImpl, float&> : BindNative {};
template<> struct BindSupport<QDataStreamReaderImpl, double&> : BindNative {};
template<typename T> struct BindSupport<QDataStreamReaderImpl,T&,typename std::enable_if<std::is_integral<T>::value>::type> : BindNative {};
......@@ -83,7 +83,7 @@ protected:
bool _null() { set(QJsonValue( )); return true; }
bool _bind(const char* s) { set(QJsonValue(s)); return true; }
// Natively supported overloads
// BindNative overloads
bool _bind( bool& b) { set(QJsonValue(b)); return true; }
bool _bind( double& d) { set(QJsonValue(d)); return true; }
......@@ -227,7 +227,7 @@ protected:
escape ( s );
return io->write( "\"" ); }
// Natively supported overloads
// BindNative overloads
bool _bind( bool& n) { return io->write( n? "true" : "false" ); }
bool _bind( float& n) { return io->write(QByteArray::number(n, 'g', std::numeric_limits< float>::max_digits10)); }
bool _bind( double& n) { return io->write(QByteArray::number(n, 'g', std::numeric_limits<double>::max_digits10)); }
......@@ -344,7 +344,7 @@ protected:
reportError(qBindExpectedText);
return false; }
// Natively supported overloads
// BindNative overloads
bool _bind( bool& b) { if (get('t', "[{\"ntf-0123456789.") &&
get('r', "[{\"" ) &&
get('u', "[{\"" ) &&
......
......@@ -46,8 +46,9 @@
// Extensible set of TResult implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder and QBind<_,QJsonValue> support
#include "QCbor_impl.h" // CborWriter demonstrating the performance potential of the approach
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder and QBind<_,QJsonValue> support
#include "QCbor_impl.h" // CborWriter demonstrating the performance potential of the approach
#include "QDataStream_impl.h" // QDataStreamReader, QDataStreamWriter demonstrating a QDataStream with indefinite length Sequence but implicit types for benchmarking
// //////////////////////////////////////////////////////////////////////////
// QBind<_,T> basic example using an internal bind<TResult> method
......@@ -63,7 +64,7 @@ struct Person
.bind(firstName)
.bind(lastName)
.bind(height)
.bind(age) // .any() ignored
.bind(age) // or .any() to ignore
.bind(phones) // recursive calls to QBind will take care of that part
; // automagically closes all opened structures
}
......@@ -86,16 +87,16 @@ public:
operator bool() { return io; } // for QMovedWriter
protected:
friend class QMovedWriter<TextWriter>;
template<class T_> friend class Val; // enables calling methods below through operator->()
template<class T_> friend class Val; // enables calling methods below
bool _null() { return true ; }
bool _sequence() { return io->write("["); }
bool _bind(const char* s) { return io->write( s ); }
template<class T_> friend class Seq; // enables calling methods below through operator->()
template<class T_> friend class Seq; // enables calling methods below
bool _item(int min= 1) { Q_UNUSED(min); return io->write(" "); }
bool _out(int max=-1) { Q_UNUSED(max); return io->write("]"); }
bool _item() { return io->write(" "); }
bool _out() { return io->write("]"); }
private:
QIODevice* io = nullptr; // for QMovedWriter
};
......@@ -155,19 +156,33 @@ int main()
QString s;
QBuffer b;
b.open(QIODevice::ReadWrite);
QDataStream d(&b);
GROUP("<atoms")
{
START {
b.seek(0); b.buffer().clear();
QDataStream(&b)
<< 1.333333333333f
<< PI
<< text
<< false
QDataStream(&b) << '['
<< ' ' << 1.333333333333f
<< ' ' << PI
<< ' ' << text
<< ' ' << false
<< ']'
;
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
QDataStream d(&b);
DataStreamWriter(&d)
.sequence()
.bind(1.333333333333f)
.bind(PI)
.bind(text)
.bind(false)
;
}
STOP("DataStream",QString::fromUtf8(b.buffer().toHex()));
START {
s.clear();
QDebug(&s)
......@@ -233,11 +248,18 @@ int main()
START {
b.seek(0); b.buffer().clear();
QDataStream data(&b);
data << '[';
for (int i=0; i < 16; i++) {
data << transform[i];
data << ' ' << transform[i];
};
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
QDataStream d(&b);
DataStreamWriter(&d).bind(transform);
}
STOP("DataStream",QString::fromUtf8(b.buffer().toHex()));
START {
s.clear();
QDebug data(&s);
......@@ -278,24 +300,31 @@ int main()
{
START {
b.seek(0); b.buffer().clear();
QDataStream(&b)
<< person.firstName.constData()
<< person. lastName.constData()
<< person. height
<< person. age
<< person. phones
QDataStream(&b) << '['
<< ' ' << person.firstName.constData()
<< ' ' << person. lastName.constData()
<< ' ' << person. height
<< ' ' << person. age
<< ' ' << person. phones
<< ']'
;
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
START {
b.seek(0); b.buffer().clear();
QDataStream d(&b);
DataStreamWriter(&d).bind(person);
}
STOP("DataStream",QString::fromUtf8(b.buffer().toHex()));
START {
s.clear();
QDebug(&s) << '['
<< person.firstName << '|'
<< person. lastName << '|'
<< person. height << '|'
<< person. age << '|'
<< person. phones << '|'
;
<< person.firstName << '|'
<< person. lastName << '|'
<< person. height << '|'
<< person. age << '|'
<< person. phones << '|'
;
}
STOP("QDebug",s);
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