Commit 92d86206 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

removing TResult using IBind

Fixed QColor except pad member Phone cannot be equal to QDataStream when using reflection (enum cast to int)
parent 905e024f
......@@ -159,7 +159,7 @@ native types simplifying again the implementations (see TextWriter example).
IWriter and IReader provide partial IBind implementations simplifying the work of implementors and offering default textual representations.
*NB:* BindNative types could be extended by specifying BindSupport<TImpl,T> trait but then, (de)serialization code must be specialized
*NB:* BindNative types could be extended by specifying BindSupport<T> trait but then, (de)serialization code must be specialized
for each TImpl. For instance, a QBind<QColor,QDataStream> may be implemented differently from QBind<QColor,IBind> but QBind<QColor>
example shows that meta() can also be used to avoid specialized serialization code that breaks RW2 requirement. If meta() is deemed
enough, the BindSupport trait and TImpl template parameters can be removed.
#include "QBind.h"
extern QIdentifierLiteral qBindExpectedItem ("ExpectedItem" );
extern QIdentifierLiteral qBindExpectedNull ("ExpectedNull" );
extern QIdentifierLiteral qBindExpectedSequence ("ExpectedSequence" );
extern QIdentifierLiteral qBindExpectedRecord ("ExpectedRecord" );
extern QIdentifierLiteral qBindExpectedText ("ExpectedText" );
extern QIdentifierLiteral qBindExpectedBytes ("ExpectedBytes" );
extern QIdentifierLiteral qBindExpectedInteger ("ExpectedInteger" );
extern QIdentifierLiteral qBindExpectedDecimal ("ExpectedDecimal" );
extern QIdentifierLiteral qBindExpectedSmallerNumber ("ExpectedSmallerNumber" );
extern QIdentifierLiteral qBindExpectedPositiveNumber("ExpectedPositiveNumber");
extern QIdentifierLiteral qBindExpectedBoolean ("ExpectedBoolean" );
extern QIdentifierLiteral qBindExpectedConstant ("ExpectedConstant" );
QIdentifierLiteral qBindExpectedItem ("ExpectedItem" );
QIdentifierLiteral qBindExpectedNull ("ExpectedNull" );
QIdentifierLiteral qBindExpectedSequence ("ExpectedSequence" );
QIdentifierLiteral qBindExpectedRecord ("ExpectedRecord" );
QIdentifierLiteral qBindExpectedText ("ExpectedText" );
QIdentifierLiteral qBindExpectedBytes ("ExpectedBytes" );
QIdentifierLiteral qBindExpectedInteger ("ExpectedInteger" );
QIdentifierLiteral qBindExpectedDecimal ("ExpectedDecimal" );
QIdentifierLiteral qBindExpectedSmallerNumber ("ExpectedSmallerNumber" );
QIdentifierLiteral qBindExpectedPositiveNumber("ExpectedPositiveNumber");
QIdentifierLiteral qBindExpectedBoolean ("ExpectedBoolean" );
QIdentifierLiteral qBindExpectedConstant ("ExpectedConstant" );
extern QIdentifierLiteral qBindIgnoredItem ("IgnoredItem" );
extern QIdentifierLiteral qBindIgnoredItemName ("IgnoredItemName" );
extern QIdentifierLiteral qBindIgnoredCharacter ("IgnoredCharacter" );
extern QIdentifierLiteral qBindIgnoredBytes ("IgnoredBytes" );
QIdentifierLiteral qBindIgnoredItem ("IgnoredItem" );
QIdentifierLiteral qBindIgnoredItemName ("IgnoredItemName" );
QIdentifierLiteral qBindIgnoredCharacter ("IgnoredCharacter" );
QIdentifierLiteral qBindIgnoredBytes ("IgnoredBytes" );
extern QIdentifierLiteral qmDataStreamVersion ("qmDataStreamVersion" );
extern QIdentifierLiteral qmColumns ("columns" );
extern QIdentifierLiteral qmSizes ("sizes" );
extern QIdentifierLiteral qmChildren ("children" );
extern QIdentifierLiteral qmName ("name" );
extern QIdentifierLiteral qmColor ("color" );
QIdentifierLiteral qmDataStreamVersion ("qmDataStreamVersion" );
QIdentifierLiteral qmColumns ("columns" );
QIdentifierLiteral qmSizes ("sizes" );
QIdentifierLiteral qmChildren ("children" );
QIdentifierLiteral qmName ("name" );
QIdentifierLiteral qmColor ("color" );
Val<Cursor> Cursor::value() noexcept { return Val<Cursor>(std::move(*this)); }
This diff is collapsed.
......@@ -473,9 +473,9 @@ private:
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
template<class TResult> //=Cursor
struct QBind<QCborValue, TResult> {
static TResult bind(Val<TResult>&& v, QCborValue&& j) {
template<>
struct QBind<QCborValue> {
static Cursor bind(Val<Cursor>&& v, QCborValue&& j) {
if (v->mode()==Write) {
if (j.isMap ()) return v.bind(j.toMap ());
if (j.isArray ()) return v.bind(j.toArray ());
......@@ -488,14 +488,14 @@ struct QBind<QCborValue, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QCborValue& j) {
static Cursor bind(Val<Cursor>&& v, QCborValue& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
TResult r;
Cursor r;
{
QScopedChoice<Val<TResult>> choice(v);
QScopedChoice choice(v);
QCborArray a; if ((r = v.bind(a))) { j = a ; return r; }
QCborMap o; if ((r = v.bind(o))) { j = o ; return r; }
QString t; if ((r = v.bind(t))) { j = QCborValue( t ); return r; }
......@@ -513,9 +513,9 @@ struct QBind<QCborValue, TResult> {
}
};
template<class TResult> //=Cursor
struct QBind<QCborArray, TResult> {
static TResult bind(Val<TResult>&& v, QCborArray&& j) {
template<>
struct QBind<QCborArray> {
static Cursor bind(Val<Cursor>&& v, QCborArray&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.sequence(&size));
......@@ -526,13 +526,13 @@ struct QBind<QCborArray, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QCborArray& j) {
static Cursor bind(Val<Cursor>&& v, QCborArray& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
auto s(v.sequence());
Val<Seq<TResult>> i;
Val<Seq<Cursor>> i;
while ((i = s.item())) {
QCborValue json;
if ((s = i.bind(json)))
......@@ -544,9 +544,9 @@ struct QBind<QCborArray, TResult> {
}
};
template<class TResult> //=Cursor
struct QBind<QCborMap, TResult> {
static TResult bind(Val<TResult>&& v, QCborMap&& j) {
template<>
struct QBind<QCborMap> {
static Cursor bind(Val<Cursor>&& v, QCborMap&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto r(v.record(&size));
......@@ -561,13 +561,13 @@ struct QBind<QCborMap, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QCborMap& j) {
static Cursor bind(Val<Cursor>&& v, QCborMap& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
auto s(v.record());
QIdentifier k; Val<Rec<TResult>> i;
QIdentifier k; Val<Rec<Cursor>> i;
while ((i = s.item(k))) {
QCborValue json;
if ((s = i.bind(json)))
......
......@@ -62,18 +62,32 @@ public:
BindMode mode() const noexcept { return BindMode::Write; }
// Shortcuts
Val<Cur<QDataWriter>> value ( ) { return Cur<QDataWriter>(this).value(); }
Seq<Cur<QDataWriter>> sequence(quint32* s=nullptr) { return Cur<QDataWriter>(this).value().sequence(s); }
Val<Cursor> value ( ) { return Cursor(this).value(); }
Seq<Cursor> sequence(quint32* s=nullptr) { return Cursor(this).value().sequence(s); }
template<typename T> Cur<QDataWriter> bind(T&& t) { return Cur<QDataWriter>(this).value().bind(std::forward<T>(t)); }
template<typename T> Cursor bind(T&& t) { return Cursor(this).value().bind(std::forward<T>(t)); }
protected:
friend class Cur<QDataWriter>;
bool _sequence(quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _record (quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _null ( ) { *io << nullptr; return true; }
bool _bind ( QUtf8DataView u) { QByteArray ba = QByteArray::fromRawData(u.data(), u.size()+int(sizeof('\0'))); return _bind(ba); }
template<typename T>
bool _bind ( T&& t) { *io << t; return true; }
friend class Cursor;
bool _sequence(quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _record (quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _null ( ) { *io << nullptr; return true; }
bool _bind ( QUtf8DataView u) { QByteArray ba = QByteArray::fromRawData(u.data(), u.size()+int(sizeof('\0'))); return static_cast<IBind*>(this)->_bind(ba); }
bool _bind ( QUtf8Data&& t) { *io << t.utf8(); return true; }
bool _bind ( QString&& t) { *io << t; return true; }
bool _bind ( bool&& t) { *io << t; return true; }
bool _bind ( qint8&& t) { *io << t; return true; }
bool _bind ( quint8&& t) { *io << t; return true; }
bool _bind ( qint16&& t) { *io << t; return true; }
bool _bind ( quint16&& t) { *io << t; return true; }
bool _bind ( qint32&& t) { *io << t; return true; }
bool _bind ( quint32&& t) { *io << t; return true; }
bool _bind ( qint64&& t) { *io << t; return true; }
bool _bind ( quint64&& t) { *io << t; return true; }
bool _bind ( float&& t) { *io << t; return true; }
bool _bind ( double&& t) { *io << t; return true; }
bool _bind ( QByteArray&& t) { *io << t; return true; }
bool _bind ( QVariant&& t) { *io << t; return true; }
bool _isOk() noexcept { return io && io->status()==QDataStream::Ok; }
......@@ -87,7 +101,6 @@ private:
QDataStream* io;
QAsciiData version;
};
template<typename T> struct BindSupport<T ,QDataWriter> : BindNative {}; //!< \remark Use meta() or QVariant to encapsulate Ts that are not statically known (provided qRegisterMetaType<T>() and qRegisterMetaTypeStreamOperators<T>() are called)
// --------------------------------------------------------------------------
......
......@@ -506,9 +506,9 @@ private:
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
template<class TResult> //=Cursor
struct QBind<QJsonValue, TResult> {
static TResult bind(Val<TResult>&& v, QJsonValue&& j) {
template<>
struct QBind<QJsonValue> {
static Cursor bind(Val<Cursor>&& v, QJsonValue&& j) {
if (v->mode()==Write) {
if (j.isObject()) return v.bind(j.toObject());
if (j.isArray ()) return v.bind(j.toArray ());
......@@ -519,14 +519,14 @@ struct QBind<QJsonValue, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QJsonValue& j) {
static Cursor bind(Val<Cursor>&& v, QJsonValue& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
TResult r;
Cursor r;
{
QScopedChoice<Val<TResult>> choice(v);
QScopedChoice choice(v);
QJsonArray a; if ((r = v.bind(a))) { j = a ; return r; }
QJsonObject o; if ((r = v.bind(o))) { j = o ; return r; }
QString t; if ((r = v.bind(t))) { j = QJsonValue( t) ; return r; }
......@@ -542,9 +542,9 @@ struct QBind<QJsonValue, TResult> {
}
};
template<class TResult> //=Cursor
struct QBind<QJsonArray, TResult> {
static TResult bind(Val<TResult>&& v, QJsonArray&& j) {
template<>
struct QBind<QJsonArray> {
static Cursor bind(Val<Cursor>&& v, QJsonArray&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.sequence(&size));
......@@ -555,13 +555,13 @@ struct QBind<QJsonArray, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QJsonArray& j) {
static Cursor bind(Val<Cursor>&& v, QJsonArray& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
auto s(v.sequence());
Val<Seq<TResult>> i;
Val<Seq<Cursor>> i;
while ((i = s.item())) {
QJsonValue json;
if ((s = i.bind(json)))
......@@ -573,9 +573,9 @@ struct QBind<QJsonArray, TResult> {
}
};
template<class TResult> //=Cursor
struct QBind<QJsonObject, TResult> {
static TResult bind(Val<TResult>&& v, QJsonObject&& j) {
template<>
struct QBind<QJsonObject> {
static Cursor bind(Val<Cursor>&& v, QJsonObject&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.record(&size));
......@@ -587,13 +587,13 @@ struct QBind<QJsonObject, TResult> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static TResult bind(Val<TResult>&& v, QJsonObject& j) {
static Cursor bind(Val<Cursor>&& v, QJsonObject& j) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(j));
}
else if (v->mode()==Read) {
auto s(v.record());
QIdentifier k; Val<Rec<TResult>> i;
QIdentifier k; Val<Rec<Cursor>> i;
while ((i = s.item(k))) {
QJsonValue json;
if ((s = i.bind(json)))
......
......@@ -40,11 +40,11 @@
// The core of QBind proof-of-concept including:
// - a fluent interface for describing logical data structures, providing auto completion and well-formedness guarantees
// - a set of recursive QBind<T,TResult> functors binding TResult and T according to their logical data structure
// - a set of recursive QBind<T> functors binding IBind and T according to their logical data structure
#include "QBind.h"
// Extensible set of TResult implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
// Extensible set of IBind implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder, QJsonVisitor and QBind<QJsonValue,_> support
#include "QCbor_impl.h" // QCborWriter demonstrating the performance potential of the approach
......@@ -81,8 +81,7 @@ struct Person
{
QString firstName, lastName; double height; int age; QVector<Phone> phones; QString comments; QList<Person> children;
template<class TResult> //=Cursor
TResult bind(Val<TResult>&& value) { // works with value->mode()==Read as well as Write
Cursor bind(Val<Cursor>&& value) { // works with value->mode()==Read as well as Write
return value
.record("Person")
.sequence("names")
......@@ -417,7 +416,7 @@ int main(int argc, char *argv[])
}
STOP("QByteArray",ba.toHex());
QBindable<> bindables[5];
QBindable bindables[5];
START {
bindables[0] = 1.333333333333f;
bindables[1] = PI;
......@@ -513,7 +512,7 @@ int main(int argc, char *argv[])
}
STOP("QByteArray",str.toHex());
QBindable<> bindable;
QBindable bindable;
START {
bindable = transform;
}
......@@ -639,7 +638,7 @@ int main(int argc, char *argv[])
STOP("protobuf",QByteArray::fromStdString(buf).toHex());
#endif
QBindable<> bindable;
QBindable bindable;
START {
bindable = person;
}
......@@ -719,7 +718,7 @@ int main(int argc, char *argv[])
}
STOP("QByteArray",str.toHex());
QBindable<> bindable;
QBindable bindable;
START {
bindable = phone;
}
......
......@@ -6,7 +6,7 @@ Xml |<sequence><decimal>1.33333337</decimal><decimal>3.141592653589793
Variant | 1.33333 3.14159 ascii characters are common in QDebug false [ RGB:[ 45 0 186] base:255]
Cbor |85fa3faaaaabfb400921fb54442d187825617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567f4bf635247429f182d0018baff646261736518ffff
QCborStream |85fa3faaaaabfb400921fb54442d187825617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567f4bf635247429f182d0018baff646261736518ffff
Data |3ff5555560000000400921fb54442d1800000026617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567000001ffff2d2d0000baba0000
Data |3ff5555560000000400921fb54442d1800000026617363696920636861726163746572732061726520636f6d6d6f6e20696e2051446562756700002d00baff
QDataStream |3ff5555560000000400921fb54442d1800000026617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567000001ffff2d2d0000baba0000
QByteArray |abaaaa3f182d4454fb210940617363696920636861726163746572732061726520636f6d6d6f6e20696e205144656275670001000000ffff2d2d0000baba00000000
Bindables |
......@@ -49,7 +49,7 @@ Xml |<Phone><Home>2</Home><number>+44 1234567</number></Phone>
Variant | number:+44 1234567 type:2
Cbor |bf647479706502666e756d6265726b2b34342031323334353637ff
QCborStream |bf647479706502666e756d6265726b2b34342031323334353637ff
Data |0200000016002b0034003400200031003200330034003500360037
Data |0000000200000016002b0034003400200031003200330034003500360037
QDataStream |0200000016002b0034003400200031003200330034003500360037
QByteArray |022b34342031323334353637
Bindable |
......@@ -57,11 +57,11 @@ Bindable>Cbor |bf647479706502666e756d6265726b2b34342031323334353637ff
Bindable>Json |{"type":2,"number":"+44 1234567"}
Person<>Json |================================================================================
Json>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] | IgnoredCharacter 0:1 IgnoredCharacter 0:15 IgnoredCharacter 0:23 IgnoredCharacter 0:40 IgnoredCharacter 0:42 IgnoredCharacter 0:58 IgnoredCharacter 0:102
P>Json |{"names":["John","Doe"],"height":1.7500000000000002,"age":-1,"phones":[],"comments":"","children":[]}
P>Json |{"names":["John","Doe"],"height":1.75,"age":-1,"phones":[],"comments":"","children":[]}
Json>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] |
P>JsonValue |{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]}
P>JsonValue |{"age":-1,"children":[],"comments":"","height":1.75,"names":["John","Doe"],"phones":[]}
JsonValue>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] |
Json>JsonValue|{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]} |
Json>JsonValue|{"age":-1,"children":[],"comments":"","height":1.75,"names":["John","Doe"],"phones":[]} |
Json>Cbor |bf656e616d65739f644a6f686e63446f65ff66686569676874fa3fe0000063616765206670686f6e65739fff68636f6d6d656e747360686368696c6472656e9fffff
Person<>Cbor |================================================================================
Cbor>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] |
......
Markdown is supported
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