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

Added custom bind example using lambda (~ Python list comprehension)

parent 5f7376e2
......@@ -170,6 +170,8 @@ struct QBindDefault {
template<class T_> class Rec; //!< a Record data structure defined below
template<class T_> class Seq; //!< a Sequence data structure defined below
template<class T_> using QBindSeqFunction = std::function<Seq<T_>&&(Seq<T_>&&)>;
template<class T_> class Val //!< a choice of sequence(), record(), null(), or any value with at least a textual representation and possibly binary ones
{
Q_DISABLE_COPY(Val)
......@@ -197,7 +199,6 @@ public:
/**/ Rec<T_> record ( quint32 s) { return record (&s); }
// Shortcuts
template<typename Ts, typename T> T_ sequenceFrom(Ts&& ts, std::function<TResult(Val<TResult>, T t)> itemsBind);
template<typename T> Seq<T_> operator<<( T&& t) { return sequence().bind(std::forward<T>(t)); } // stream compatible
/**/ Rec<T_> record (QName n) { return meta({{qmName,n}}).record(); }
private:
......@@ -223,6 +224,7 @@ public:
Val<Seq<T_>> item() { return outer->_item() ? Val<Seq<T_>>(std::move(*this)) : Val<Seq<T_>>(); }
// Shortcuts
template<typename Ts, typename T = typename Ts::value_type> Seq<T_> from(Ts& ts, std::function<TResult(Val<TResult>&&, T& t)> itemBind);
/**/ Seq<Seq<T_>> sequence(quint32* s=nullptr) { return item().sequence ( s); }
/**/ Rec<Seq<T_>> record (quint32* s=nullptr) { return item().record ( s); }
/**/ Seq<T_> null ( ) { return item().null ( ); }
......@@ -230,11 +232,15 @@ public:
template<typename T> Seq<T_> bind ( T&& t) { return item().bind(std::forward<T>(t)); }
template<typename T> Rec<T_> bind (T& t, T&& defaultT) { return item().bind(t,std::forward<T>(defaultT)); }
// Sequence comprehension support
Seq<T_> bindFrom(QBindSeqFunction<TResult> customBind) { customBind(std::move(unsafeThis())); return std::move(*this); }
// Stream compatible shortcut
template<typename T> Seq<T_> operator<<(T&& t) { return item().bind(std::forward<T>(t)); }
private:
template<typename T, class TResult, typename TEnabledIf> friend struct QBind;
Val<TResult> unsafeItem() noexcept { return outer->_item() ? Val<TResult>(outer._unsafeCopy()) : Val<TResult>(); }
Seq<TResult> unsafeThis() noexcept { return Seq<TResult>(outer->_unsafeCopy()) ; }
T_ outer = T_();
};
......@@ -759,15 +765,26 @@ public:
template<class T_>
template<typename Ts, typename T>
T_ Val<T_>::sequenceFrom(Ts&& ts, std::function<TResult(Val<TResult>, T t)> itemsBind) {
if (this->mode()==Write) {
auto s(sequence());
Seq<T_> Seq<T_>::from(Ts& ts, std::function<TResult(Val<TResult>&&, T& t)> itemBind) {
if ((*this)->mode()==Write) {
for (T t : ts) {
itemsBind(s._unsafeCopy(), t);
itemBind(unsafeItem(), t);
}
}
else if (this->mode()==Read) {
// TODO
else if ((*this)->mode()==Read) {
auto&& i = ts.begin();
Val<typename T_::TResult> item;
while ((item = unsafeItem())) {
if (i != ts.end()) {
itemBind(std::move(item), *i);
}
else {
T newItem;
if (itemBind(std::move(item), newItem)) {
ts.insert(i, newItem);
}
}
}
}
else { Q_ASSERT_X(!this, Q_FUNC_INFO, "Unsupported implementation mode()"); return null(); }
}
......
......@@ -64,7 +64,8 @@ class QModelWriter : public IWriter
public:
QModelWriter(QAbstractItemModel* m, bool rowFirst=true) : m(m), rowFirst(rowFirst), w(&io) { Q_ASSERT(m); }
Val<Cursor> meta(QMetaData&& m) { return Cursor(this).value().meta(m); }
Seq<Cursor> sequence( ) { return Cursor(this).value().sequence( ); }
Val<Cursor> meta (QMetaData&& m) { return Cursor(this).value().meta (m); }
protected:
void _meta(QMetaData& meta) {
if (T==d) {
......
......@@ -221,6 +221,17 @@ public:
// //////////////////////////////////////////////////////////////////////////
// Tests and Benchmarks
// Base dataset
static const char* ascii = "ascii characters are common in QDebug";
static QColor color(45,0,186);
static QVector<double> transform{1./3, 2./3, 1./3, 1.,
2./3, 1./3, 2./3, 1.,
1./3, 2./3, 1./3, 1.,
0. , 0. , 0. , 1.};
static Person person{"John","Doe",1.75,18,{},"unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ",QList<Person>()};
static const double PI=3.141592653589793;
static Phone phone {Phone::Home,"+44 1234567"};
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qfile.h>
#include <QtCore/qdir.h>
......@@ -235,7 +246,7 @@ public:
// NB: It is not possible to use QBENCHMARK to evaluate qDebug because it installs a specific handler
#define GROUP(group) { \
#define GROUP(group) if (argc<=1 || strcmp(argv[1],group)==0) { \
double previousTotal=0., groupTotal=0.; \
bool groupWarmup; \
do { \
......@@ -254,6 +265,8 @@ static QElapsedTimer item;
auto usecs=double(item.nsecsElapsed())/1000/123; groupTotal+=usecs; \
if (previousTotal<0.01) { fprintf(results,"|%14s", label); fprintf(samples, "%-14s|%s\n", label, qUtf8Printable(result)); } else fprintf(results,"|%14.1f", usecs); }
void doGuiExample();
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
......@@ -264,16 +277,6 @@ int main(int argc, char *argv[])
if (!(results && samples))
return -1;
// Read-only args
const char* ascii = "ascii characters are common in QDebug";
QColor color(45,0,186);
QVector<double> transform{1./3, 2./3, 1./3, 1.,
2./3, 1./3, 2./3, 1.,
1./3, 2./3, 1./3, 1.,
0. , 0. , 0. , 1.};
Person person{"John","Doe",1.75,18,{},"unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ",QList<Person>()};
const double PI=3.141592653589793;
// Temporary buffers
QString s;
QByteArray ba; ba.reserve(1000);
......@@ -641,8 +644,6 @@ int main(int argc, char *argv[])
STOP("Writable>Json",b.buffer());
}
GROUP_STOP
Phone phone {Phone::Home,"+44 1234567"};
GROUP("Phone>")//=========================================================
{
START {
......@@ -943,28 +944,76 @@ int main(int argc, char *argv[])
}
GROUP_STOP
{
// Adapt dataset to different views
person.firstName="";
person.comments="";
person.phones.append(phone);
QVector<Person> persons; persons << person << person;
persons[0].age=42;
persons[0].children.append(person);
persons[1].age=41;
QStandardItemModel treeModel; QModelWriter<>(& treeModel ).meta({{qmChildren,"children"}/*,{qmColumns ,"names,age"}*/}).bind(persons);
QStandardItemModel tableModel; QModelWriter<>(& tableModel ).meta({{qmColumns ,"names,age,children"}}).bind(persons);
QStandardItemModel matrixModel; QModelWriter<>(&matrixModel,false).meta({{qmSizes ,"4,3"}}).bind(transform);
QDialog dlg;
auto layout = new QHBoxLayout(&dlg); dlg.setLayout(layout);
auto tree = new QTreeView (&dlg); layout->addWidget(tree ); tree ->setModel(& treeModel); for(int i=0; i<treeModel.columnCount(); i++) tree ->resizeColumnToContents(i);
auto table = new QTableView (&dlg); layout->addWidget(table ); table ->setModel(& tableModel); table ->resizeColumnsToContents();
auto matrix = new QTableView (&dlg); layout->addWidget(matrix); matrix->setModel(&matrixModel); matrix->resizeColumnsToContents();
dlg.resize(1024,320);
dlg.exec();
if (argc<=1 || strcmp(argv[1],"gui")==0) {
doGuiExample();
}
return (fclose(samples)==0) &/*anyway*/ (fclose(results)==0);
}
Seq<Cursor>&& flatten(const QList<Person>& ps, Seq<Cursor>&& s) {
for (auto&& p : ps) {
s = s
.record()
.bind("first name", p.firstName )
.bind("height(ft)", p.height*3.28)
.out()
.bindFrom([&](Seq<Cursor>&& s){
return std::move(flatten(p.children, std::move(s)));
});
}
return std::move(s);
};
void doGuiExample() {
// Adapt dataset to different views
person.lastName="";
person.comments="";
person.phones.append(phone);
QList<Person> persons; persons << person << person;
persons[0].age=42;
persons[0].children.append(person);
persons[0].children[0].firstName="Joe";
persons[0].children[0].age=18;
persons[0].children[0].height=1.82;
persons[1].firstName="Jane";
persons[1].age=41;
persons[0].height=1.72;
persons[1].phones.append(Phone{Phone::Office,"112"});
QStandardItemModel matrixModel; QModelWriter<>(&matrixModel,false).meta({{qmSizes ,"4,3"}}).bind(transform);
QStandardItemModel treeModel; QModelWriter<>(& treeModel ).meta({{qmChildren,"children"}/*,{qmColumns ,"names,age"}*/}).bind(persons);
QStandardItemModel tableModel; QModelWriter<>(& tableModel ).meta({{qmColumns ,"names,age,children"}}).bind(persons);
QStandardItemModel flatModel; QModelWriter<>(& flatModel ).sequence().bindFrom([&](Seq<Cursor>&& s){
return std::move(flatten(persons, std::move(s)));
});
QStandardItemModel customModel; QModelWriter<>(&customModel ).sequence().bindFrom([&](Seq<Cursor>&& s){
for (auto&& p : persons) {
s = s.record()
.bind("first name", p.firstName)
.sequence("phones")
.bindFrom([&] (Seq<Cursor>&& s) {
for (auto&& ph : p.phones) {
if (ph._t==Phone::Office) {
s = s.bind(ph);
}
}
return std::move(s);
})
.out()
.out();
}
return std::move(s);
});
QDialog dlg;
auto layout = new QHBoxLayout(&dlg); dlg.setLayout(layout);
auto matrix = new QTableView (&dlg); layout->addWidget(matrix); matrix->setModel(&matrixModel); matrix->resizeColumnsToContents();
auto tree = new QTreeView (&dlg); layout->addWidget(tree ); tree ->setModel(& treeModel); for(int i=0; i<treeModel.columnCount(); i++) tree ->resizeColumnToContents(i);
auto table = new QTableView (&dlg); layout->addWidget(table ); table ->setModel(& tableModel); table ->resizeColumnsToContents();
auto flat = new QTableView (&dlg); layout->addWidget(flat ); flat ->setModel(& flatModel); flat ->resizeColumnsToContents();
auto custom = new QTableView (&dlg); layout->addWidget(custom); custom->setModel(&customModel); custom->resizeColumnsToContents();
dlg.resize(1024,280);
dlg.exec();
}
group | QDebug| Text| Json| Xml| Variant| Cbor| QCborStream| Data| QDataStream| QByteArray| Writables|Writables>Cbor|Writables>Json|total(usecs)|variation(%)
builtin> | 16.7| 4.6| 8.0| 30.2| 11.0| 0.7| 1.6| 1.1| 0.7| 0.1| 0.1| 0.8| 7.3| 82.9| 64.2
builtin> | 10.9| 2.5| 11.0| 31.3| 12.7| 2.0| 2.2| 1.1| 0.6| 0.1| 0.1| 0.8| 8.1| 83.5| 0.6
builtin> | 8.9| 2.5| 7.1| 30.8| 11.7| 0.8| 1.6| 1.1| 0.6| 0.1| 0.1| 0.8| 7.6| 73.7| 11.7
builtin> | 8.4| 2.3| 6.5| 26.3| 10.4| 0.6| 1.4| 1.2| 0.5| 0.1| 0.1| 0.7| 6.4| 64.9| 32.1
builtin> | 8.1| 2.2| 6.2| 26.2| 9.9| 0.6| 1.4| 0.9| 0.6| 0.1| 0.1| 0.7| 6.7| 63.5| 2.1
builtin> | 7.8| 2.4| 6.1| 26.1| 9.8| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.3| 62.8| 1.1
builtin> | 7.9| 2.2| 6.2| 27.3| 10.1| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.4| 64.2| 2.3
builtin> | 11.7| 2.2| 6.2| 26.3| 10.1| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.3| 67.1| 4.6
builtin> | 7.7| 2.2| 6.1| 26.2| 9.8| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.4| 62.6| 6.7
builtin> | 9.9| 2.6| 6.2| 26.2| 9.9| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.3| 65.5| 4.6
builtin> | 8.3| 2.2| 6.2| 29.6| 9.9| 0.6| 1.4| 0.9| 0.6| 0.1| 0.1| 0.7| 6.3| 66.8| 2.1
builtin> | 7.8| 3.5| 8.8| 27.3| 10.0| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 7.1| 68.7| 2.8
builtin> | 7.8| 2.2| 6.2| 26.1| 10.3| 0.7| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.6| 63.4| 7.7
builtin> | 7.7| 2.2| 8.4| 26.1| 9.9| 0.7| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.6| 65.2| 2.8
builtin> | 7.7| 2.2| 6.3| 26.1| 9.8| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.3| 62.9| 3.7
builtin> | 7.7| 2.2| 6.2| 26.8| 9.8| 0.6| 1.4| 0.9| 0.6| 0.1| 0.1| 0.7| 6.3| 63.3| 0.7
builtin> | 7.7| 2.2| 6.1| 26.1| 9.8| 0.6| 1.4| 0.9| 0.5| 0.1| 0.1| 0.7| 6.3| 62.6| 1.2
group | QDebug| Text| Json| Xml| Variant| Cbor| QCborStream| Data| QDataStream| QByteArray| Writable| Writable>Cbor| Writable>Json|total(usecs)|variation(%)
doubles> | 21.2| 16.2| 19.1| 55.6| 25.7| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.7| 19.9| 162.4| 2.0
doubles> | 18.2| 15.9| 19.2| 61.6| 31.5| 0.8| 1.2| 1.0| 1.0| 0.3| 0.0| 0.7| 19.3| 170.8| 5.2
doubles> | 18.5| 16.2| 18.8| 58.6| 27.4| 0.8| 1.2| 1.2| 0.9| 0.3| 0.0| 0.7| 20.0| 164.5| 3.7
doubles> | 18.4| 16.0| 21.8| 59.4| 25.3| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.7| 18.3| 163.9| 0.3
doubles> | 17.1| 16.3| 17.9| 56.6| 25.4| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.8| 18.6| 156.6| 4.5
doubles> | 20.2| 14.9| 18.0| 55.1| 25.2| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.6| 21.2| 159.1| 4.0
doubles> | 17.3| 14.9| 18.1| 55.7| 26.0| 0.7| 1.4| 1.0| 0.8| 0.3| 0.0| 0.7| 17.9| 154.6| 2.8
doubles> | 17.2| 15.6| 21.1| 55.1| 25.6| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.7| 18.2| 157.3| 1.7
doubles> | 17.3| 15.1| 18.0| 55.3| 25.4| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.6| 18.4| 154.0| 2.1
doubles> | 17.3| 15.2| 18.0| 55.2| 25.6| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.6| 18.3| 154.1| 0.1
doubles> | 17.3| 15.1| 18.0| 55.5| 25.6| 0.7| 1.1| 1.0| 0.8| 0.3| 0.0| 0.6| 18.2| 154.2| 0.1
group | QDebug| Text| Json| Xml| Variant| Cbor| QCborStream| Data| QDataStream| QByteArray| Writable| Writable>Cbor| Writable>Json|total(usecs)|variation(%)
Person> | 6.3| 4.6| 11.5| 42.0| 12.0| 2.5| 3.0| 0.8| 0.5| 0.1| 0.0| 2.5| 11.6| 97.5| 2.6
Person> | 6.9| 5.0| 11.5| 41.0| 15.2| 2.8| 2.8| 0.8| 0.5| 0.1| 0.0| 2.5| 11.7| 100.9| 3.5
Person> | 8.5| 5.4| 11.4| 40.0| 11.4| 2.6| 2.8| 0.8| 0.5| 0.1| 0.0| 2.6| 11.9| 98.0| 2.9
Person> | 6.2| 4.8| 12.4| 41.8| 11.3| 2.5| 2.8| 0.8| 0.5| 0.1| 0.0| 3.2| 11.5| 98.1| 0.1
Person> | 6.4| 4.5| 11.9| 44.3| 11.5| 2.5| 2.8| 0.9| 0.5| 0.1| 0.0| 2.5| 11.5| 99.4| 1.3
Person> | 7.0| 4.5| 11.7| 24.0| 11.4| 2.5| 3.0| 0.8| 0.5| 0.1| 0.0| 2.5| 11.7| 79.8| 0.6
Person> | 6.1| 4.6| 11.3| 24.2| 12.3| 2.5| 2.9| 0.8| 0.5| 0.1| 0.0| 2.5| 11.5| 79.6| 0.2
group | QDebug| Text| Json| Xml| Variant| Cbor| QCborStream| Data| QDataStream| QByteArray| Writable| Writable>Cbor| Writable>Json|total(usecs)|variation(%)
Phone> | 2.0| 3.7| 5.4| 17.9| 5.7| 3.8| 1.1| 0.4| 0.2| 0.4| 0.0| 3.8| 5.3| 49.8| 3.3
Phone> | 2.3| 3.6| 5.4| 16.7| 5.9| 3.6| 1.1| 0.4| 0.2| 0.4| 0.0| 3.7| 5.3| 48.7| 2.3
Phone> | 2.2| 3.6| 5.7| 16.9| 5.9| 3.6| 1.1| 0.4| 0.2| 0.4| 0.0| 3.7| 5.3| 49.0| 0.8
Phone> | 2.1| 3.7| 9.0| 19.5| 5.8| 3.7| 1.1| 0.4| 0.2| 0.4| 0.0| 3.9| 5.3| 55.2| 12.6
Phone> | 2.0| 3.8| 7.6| 12.4| 6.0| 3.7| 1.1| 0.4| 0.2| 0.4| 0.0| 3.8| 5.5| 47.0| 1.0
Phone> | 2.1| 3.8| 5.7| 12.2| 6.3| 3.8| 1.1| 0.4| 0.2| 0.4| 0.0| 3.7| 5.5| 45.3| 3.5
Phone> | 2.0| 3.9| 5.6| 12.3| 5.9| 3.7| 1.1| 0.4| 0.2| 0.4| 0.0| 4.6| 5.5| 45.7| 0.8
Phone> | 2.7| 3.8| 5.7| 12.8| 5.9| 3.8| 1.1| 0.4| 0.2| 0.4| 0.0| 3.8| 5.4| 46.1| 0.7
group | Json>P| P>Json| Json>P| P>JsonValue| JsonValue>P|Json>JsonValue| Json>Cbor|total(usecs)|variation(%)
Person<>Json| 15.5| 6.5| 11.8| 11.2| 3.8| 22.4| 20.8| 92.0| 1.9
Person<>Json| 14.1| 6.4| 11.0| 14.8| 4.4| 22.2| 25.8| 98.7| 7.3
Person<>Json| 13.7| 6.0| 11.2| 14.5| 4.3| 22.3| 22.3| 94.2| 4.6
Person<>Json| 14.9| 6.4| 11.8| 12.6| 3.9| 23.6| 20.9| 94.0| 0.2
Person<>Json| 14.0| 6.5| 16.4| 11.6| 3.8| 22.5| 19.8| 94.6| 0.6
Person<>Json| 13.7| 6.0| 11.1| 10.4| 3.7| 21.1| 18.9| 84.8| 3.0
Person<>Json| 13.6| 6.1| 11.1| 10.4| 3.6| 20.9| 18.8| 84.4| 0.5
Person<>Json| 15.1| 6.1| 11.1| 10.4| 3.7| 21.0| 18.9| 86.2| 2.2
group | Cbor>P| P>Cbor| Cbor>P| QCborStream>P| P>CborValue| CborValue>P|Cbor>CborValue|CborValue>Cbor| Cbor>Json|total(usecs)|variation(%)
Person<>Cbor| 14.5| 2.9| 15.2| 5.6| 9.3| 4.4| 21.3| 11.7| 18.1| 103.0| 0.2
Person<>Cbor| 14.7| 2.5| 15.2| 5.7| 9.3| 4.4| 20.4| 12.0| 15.1| 99.3| 3.6
Person<>Cbor| 14.3| 2.6| 15.2| 6.1| 9.3| 4.4| 20.5| 7.7| 14.3| 94.5| 2.2
Person<>Cbor| 14.5| 2.6| 16.1| 5.6| 9.5| 4.3| 20.5| 7.8| 14.3| 95.2| 0.8
Person<>Cbor| 14.2| 2.5| 15.0| 5.7| 9.4| 4.5| 22.3| 7.8| 13.8| 95.3| 0.1
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