Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

main.cpp 48.4 KB
Newer Older
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/****************************************************************************
 * **
 * ** Copyright (C) 2016 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$
 * **
 * ****************************************************************************/

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
41
42
43
// The core of QTransmogrifier proof-of-concept including:
// - a QValue fluent interface for describing logical data structures, providing auto completion and well-formedness guarantees
// - a set of recursive QTransmogrifier<T> functors binding QAbstractValue and T according to their logical data structure
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
44

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
45
#include "QValue.h"
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
46

47
// Extensible set of QAbstractValue implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
48

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
49
#include "QJson_impl.h"     // QJsonWriter, QJsonReader, QJsonBuilder, QJsonVisitor and QTransmogrifier<QJsonValue,_> support
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
50
51
#include "QCbor_impl.h"     // QCborWriter demonstrating the performance potential of the approach
#include "QData_impl.h"     // QDataReader, QDataWriter demonstrating a QDataStream with implicit types for benchmarking
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
52
#include "QVariant_impl.h"  // QVariantBuilder, QVariantVisitor and QTransmogrifier<QVariant,_> support
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
53
#include "QModel_impl.h"    // Q*ModelWriter support
54
#include "QXml_impl.h"      // QXmlWriter support
55
#include "QSettings_impl.h" // QSettings* support
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
56

57
58
59
60
#ifdef PROTOBUF
#include "persons.pb.h"
#endif

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
61
62
63
64
65
#include <QtCore/qvariant.h>

#include <QtGui/qstandarditemmodel.h>
#include <QtWidgets/qtreeview.h>
#include <QtWidgets/qtableview.h>
66
#include <QtWidgets/qdialog.h>
67
68
69
#include <QtWidgets/qgridlayout.h>
#include <QtWidgets/qtabwidget.h>
#include <QtWidgets/qlabel.h>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
70
71
#include <QtWidgets/qapplication.h>

72
73
#include <tuple>

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
74
// //////////////////////////////////////////////////////////////////////////
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
75
// QValue-enabled types examples
76
77
78

// Using Qt's meta-object system

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
79
#include "data.h"
80
81

// Using an internal bind method
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
82
83
84

struct Person
{
85
    int id; QString firstName, lastName; double height; int age; QVector<Phone> phones; QString comments; QList<Person> children;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
86

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
87
    QValueStatus zap(QValue&& value) { // works with value->mode()==Read as well as Write
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
88
89
90
91
92
93
94
95
96
97
98
99
        return value
            .record("Person")
                .sequence("names")
                    .bind(firstName)
                    .bind( lastName)
                    .out()
                .bind("height"  ,height  )
                .bind("age"     ,age  ,-1) // reads null() as -1
                .bind("phones"  ,phones  ) // recursive calls to QTransmogrifier will take care of that part
                .bind("comments",comments)
                .bind("children",children)
                ; // automagically closes opened record()
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
100
101
102
    }
};

103
104
105
// For comparison purposes:

#include<QtCore/qdebug.h>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
106
QDebug &operator<<(QDebug &out, const Person &p)
107
108
109
110
111
112
113
114
115
{
    return out.nospace() << "Person(" // items count and names are implicit
            << p.firstName << ", " << p.lastName << ", " // sequence is implicit
            << p.height    << ", "
            << p.age       << ", "
            << p.phones    << ", "
            << p.comments  << ", "
            << p.children  << ")";
}
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
116
117
118
#include<QtCore/qdatastream.h>
QDataStream &operator<<(QDataStream &out, const Person &p)
{
119
    return out // record, items count and names are implicit
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
120
121
122
123
            << p.firstName << p.lastName // sequence is implicit
            << p.height
            << p.age
            << p.phones
124
            << p.comments
125
126
            << p.children
            ; // no record delimiter
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
127
}
128
//! Same as operator<<(QDataStream&, Person&) with no possibility to detect errors other than premature end of QDataStream
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
129
130
QDataStream &operator>>(QDataStream &in, Person &p)
{
131
    return in >> p.firstName >> p.lastName >> p.height >> p.age >> p.phones >> p.comments >> p.children;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
132
}
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
133

134
// Using a view type to customize an existing bind using metadata
135
136
137
138

struct PersonsView
{
    QList<Person>& persons;
139

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
140
    QValueStatus zap(QValue&& value) {
141
        return value
142
143
144
            .meta(qmChildren,"children")
            .meta(qmColumns ,"names,height,age,phones,comments") // to optimize multi-dimensional data formats
            .bind(persons);
145
146
147
    }
};

148
149
150
151
152
153
// View types can even bind nested structures into flattened tables using a foreign key to express parent 1-n children relationships

struct PersonsTable {
    QList<Person>& persons;
    PersonsTable(QList<Person>& ps) : persons(ps) {}

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
154
    QValueStatus zap(QValue&& v) {
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
        if (v->mode()==Read) {
            ids.clear();
            orphans.clear();
            persons.clear();
            Person p;
            auto s(v.sequence());
            while ((s = bind(p, std::move(s)))) {
                // merge orphans with persons at the end only
            }
            for (int parentId: orphans.keys()) {
                if (parentId && ids.contains(parentId)) {
                    ids[parentId]->children = orphans[parentId];
                }
                else {
                    persons.append(orphans[parentId]);
                }
            }
            return s;
        }
        else if (v->mode()==Write) {
            parentIds.clear();
            ids.clear();
            return flatten(persons, v.sequence());
        }
    }
private:
    QStack<int> parentIds;
    QMap<int,Person*> ids;
    QMap<int,QList<Person>> orphans;

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
185
    QSequence bind(Person& p, QSequence&& s) {
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
        if (s->mode()==Read) {
            int parentId=0;
            double height_ft=0.;
            s = s.record()
                    .bind("id"        , p.id       )
                    .bind("parent_id" , parentId   )
                    .bind("first_name", p.firstName)
                    .bind("last_name" , p.lastName )
                    .bind("height_ft" , height_ft  )
                    .bind("age"       , p.age      )
                    .bind("comments"  , p.comments ) // TODO Remove while keeping p.comments untouched
                    .bind("phones"    , p.phones   )
                    .out();
            if (s) {
                p.height = height_ft/3.28;
                orphans[parentId].append(p);
                if (p.id) {
                    Q_ASSERT(!ids.contains(p.id)); // children may be attributed to any of the duplicates
                    ids.insert(p.id, &orphans[parentId].last());
                }
            }
            return std::move(s);
        }
        else if (s->mode()==Write) {
            if (!p.id) {
                int newId=(2019-p.age)*10;
                while (ids.contains(newId)) {
                    newId++;
                    Q_ASSERT(newId<(2020-p.age)*10);
                }
                p.id = newId;
                ids.insert(p.id,&p);
            }

            s = s.record()
                    .bind("id"        , p.id)
                    .bind("parent_id" , parentIds.isEmpty() ? 0 : parentIds.back())
                    .bind("first_name", p.firstName  )
                    .bind("last_name" , p.lastName )
                    .bind("height_ft" , p.height*3.28)
                    .bind("age"       , p.age      )
                    .bind("comments"  , p.comments )
                    .bind("phones"    , p.phones   )
                    .out();

            parentIds.push_back(p.id);
            s = flatten(p.children, std::move(s));
            parentIds.pop_back();

            return std::move(s);
        }
    }

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
239
    QSequence flatten(QList<Person>& ps, QSequence&& s) {
240
241
242
243
244
245
246
        for (auto&& p : ps) {
            s = bind(p, std::move(s));
        }
        return std::move(s);
    }
};

247
// //////////////////////////////////////////////////////////////////////////
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
248
// QTransmogrifier<T> examples using external bind methods
249
250
251

#include <QtGui/qcolor.h>

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
252
//! QTransmogrifier<QColor> with special support for QDataStream compatibility using meta()
253
template<>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
254
struct QTransmogrifier<QColor> {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
255
    static QValueStatus zap(QValue&& v, QColor&& c) {
256
        QColor copy(c);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
257
        return zap(std::move(v),copy);
258
    }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
259
    static QValueStatus zap(QValue&& v, QColor& c) {
260
261
262
        if (!c.isValid()) {
            return v.null();
        }
263
264
265
266
267
268
269
270
        QIdentifierLiteral n;
        QAsciiData m;
        do {
            v=v.meta(n, m);
            if (n==qmDataStreamVersion) {
                if (m.utf8().toInt()<7) { v->reportError("UnsupportedQDataStreamVersion");
                    return v.null();
                }
271
272
                QRgba64 c64 = c.rgba64();
                return v.sequence().bind(quint8(c.spec())).bind(quint16(c64.alpha())).bind(quint16(c64.red())).bind(quint16(c64.green())).bind(quint16(c64.blue())).bind(quint16(0)); // TODO pad
273
            }
274
        } while (!n.isNull());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
275
        QRecord r = v.record();
276
        switch(c.spec()) {
277
278
279
        case QColor::Spec::Rgb : r = r.sequence("RGB" ).bind(quint8(c.red   ())).bind(quint8(c.green        ())).bind(quint8(c.blue     ()))                        .out(); break;
        case QColor::Spec::Hsl : r = r.sequence("HSL" ).bind(qint16(c.hslHue())).bind(quint8(c.hslSaturation())).bind(quint8(c.lightness()))                        .out(); break;
        case QColor::Spec::Hsv : r = r.sequence("HSV" ).bind(qint16(c.hsvHue())).bind(quint8(c.hsvSaturation())).bind(quint8(c.value    ()))                        .out(); break;
280
        case QColor::Spec::Cmyk: r = r.sequence("CMYK").bind(quint8(c.cyan  ())).bind(quint8(c.magenta      ())).bind(quint8(c.yellow   ())).bind(quint8(c.black())).out(); break;
281
282
        default: Q_ASSERT(false);
        }
283
284
        if (c.alpha()<255) { r = r.bind("alpha",quint8(c.alpha())); }
        return r.bind("base",quint8(255)); // Explicits ARGBCMYKSLV components' base (H base is 360 corresponding to color wheel degrees, with -1 used for gray in addition to S being 0)
285
                                                  // QDebug use of float values removes need for base but may lose precision
286
287
288
    }
};

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
289
// //////////////////////////////////////////////////////////////////////////
290
// QAbstractValue basic implementation example
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
291
292

#include <type_traits>
293
#include <QtCore/qbytearray.h>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
294

295
class TextWriter : public QAbstractValueWriter
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
296
297
{
    Q_DISABLE_COPY(TextWriter)
298
    Q_ENABLE_MOVE_DEFAULT(TextWriter)
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
299
public:
300
    TextWriter(QByteArray* utf8) : utf8(utf8) { Q_ASSERT(utf8); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
301
302

    // Shortcuts
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
303
304
    template<typename T> QSequence     operator<<(T&& t) { return QValueStatus(this).value().sequence().item().bind(std::forward<T>(t)); }
    template<typename T> QValueStatus  bind      (T&& t) { return QValueStatus(this).value()                  .bind(std::forward<T>(t)); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
305
protected:
306
307
308
309
310
311
    bool trySequence(quint32* =nullptr) { if (0<level++) utf8->append("["); return true; }
    bool tryRecord  (quint32* =nullptr) { if (0<level++) utf8->append("["); return true; }
    bool tryNull    (                 ) {                                   return true; }
    bool tryBind    (  QUtf8DataView u) { utf8->append(u.data(), u.size()); return true; }
    bool tryBind    (        float&& n) { static QByteArray s; s.setNum(double(n),'g',6); return tryBind(QUtf8DataView(s.constData(), s.size())); } // with QDebug precision
    bool tryBind    (       double&& n) { static QByteArray s; s.setNum(       n ,'g',6); return tryBind(QUtf8DataView(s.constData(), s.size())); } // with QDebug precision
312

313
314
315
    bool tryItem(QIdentifier& n) { utf8->append(" ").append(n.utf8()).append(":"); return true; }
    bool tryItem(              ) { utf8->append(" ")                             ; return true; }
    bool tryOut (              ) { if (0<--level) utf8->append("]")              ; return true; }
316

317
    void _meta(QIdentifierLiteral& n, QAsciiData& m) { if (n==qmName) utf8->append('(').append(m.utf8()).append(")"); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
318
private:
319
    template<class T> friend class QModelWriter;
320
    QByteArray* utf8;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
321
    int level = 0;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
322
323
};

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
324
class Text
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
325
{
326
    QByteArray result;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
327
public:
328
    template<typename T> Text(T&& t) { TextWriter(&result).bind(std::forward<T>(t)); }
329
330
    const QByteArray& utf8() const { return result; }
    operator    QByteArray() const { return result; }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
331
332
333
334
335
};

// //////////////////////////////////////////////////////////////////////////
// Tests and Benchmarks

336
337
338
339
340
341
342
// 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.};
343
static Person person{0,"John","Doe",1.75,18,{},"unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ",QList<Person>()};
344
345
346
static const double PI=3.141592653589793;
static Phone phone {Phone::Home,"+44 1234567"};

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
347
348
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qfile.h>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
349
#include <QtCore/qdir.h>
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
350
351
352
353
354
355
#include <QtCore/qbuffer.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qdebug.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qcborstream.h>
356

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
357
358
359
360
#include <QtGui/qcolor.h>

// NB: It is not possible to use QBENCHMARK to evaluate qDebug because it installs a specific handler

361
#define GROUP(group) if (argc<=1 || strcmp(argv[1],group)==0) { \
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
362
363
364
365
366
367
    double previousTotal=0., groupTotal=0.; \
    bool groupWarmup; \
    do { \
    groupWarmup=(previousTotal<0.01 || std::abs(groupTotal-previousTotal)*100/previousTotal > 1.); \
    previousTotal=groupTotal; \
    groupTotal=0.; \
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
368
    if (previousTotal<0.01) { fprintf(results,"============"); fprintf(samples, "%-14s|================================================================================\n", group); } else fprintf(results,"%-12s",group);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
369
370
371
372
373
374
375
376
377

#define GROUP_STOP \
    if (previousTotal<0.01) fprintf(results,"|total(usecs)|variation(%%)\n"); else fprintf(results,"|%12.1f|%5.1f\n", groupTotal, previousTotal>=0.01 ? std::abs(groupTotal-previousTotal)*100/previousTotal : 0); \
    } while (groupWarmup); }

static QElapsedTimer item;
#define START item.start(); for (int i=0; i<123; ++i)
#define STOP(label,result) { \
    auto usecs=double(item.nsecsElapsed())/1000/123; groupTotal+=usecs; \
378
    if (previousTotal<0.01) { fprintf(results,"|%14s", label); fprintf(samples, "%-14s|%s\n", label, qUtf8Printable(result)); } else fprintf(results,"|%14.1f", usecs); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
379

380
381
void doGuiExample();

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
382
383
384
385
386
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Generated files
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
387
388
    FILE* results; fopen_s(&results, QString("../QBind/results-%1.csv").arg(QDir::current().dirName()).toLocal8Bit().constData(), "w");
    FILE* samples; fopen_s(&samples,         "../QBind/samples.txt"                                                             , "w");
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
389
390
391
392
393
    if (!(results && samples))
        return -1;

    // Temporary buffers
    QString s;
394
395
    QByteArray ba; ba.reserve(1000);
    QBuffer b(&ba); b.open(QIODevice::ReadWrite);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
396
397
    QVariant v;
    QDataStream d(&b);
398

399
400
    qRegisterMetaTypeStreamOperators<QUtf8Data>();

401
    GROUP("builtin>")//========================================================
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
402
403
    {
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
404
            s.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
405
406
407
408
409
410
411
412
413
414
            QDebug(&s)
                << 1.333333333333f
                << PI
                << ascii
                << false
                << color
                ;
        }
        STOP("QDebug",s);
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
415
            ba.resize(0);
416
            TextWriter(&ba)
417
418
419
420
421
                << 1.333333333333f
                << PI
                << ascii
                << false
                << color
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
422
423
                ;
        }
424
        STOP("Text",b.buffer());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
425
        START {
426
427
            ba.resize(0);
            QJsonWriter(&ba).sequence()
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
428
429
430
431
432
433
434
                .bind(1.333333333333f)
                .bind(PI)
                .bind(ascii)
                .bind(false)
                .bind(color)
                ;
        }
435
        STOP("Json",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
436
437
438
439
440
441
442
443
444
445
446
        START {
            ba.resize(0);
            QXmlStreamWriter w(&ba);
            QXmlWriter(&w).sequence()
                .bind(1.333333333333f)
                .bind(PI)
                .bind(ascii)
                .bind(false)
                .bind(color)
                ;
        }
447
        STOP("Xml",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
448
449
450
451
452
453
454
455
456
457
        START {
            v.clear();
            QVariantBuilder(&v).sequence()
                .bind(1.333333333333f)
                .bind(PI)
                .bind(ascii)
                .bind(false)
                .bind(color)
                ;
        }
458
        STOP("Variant",Text(v).utf8());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
459
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
460
            ba.resize(0);
461
            QCborWriter(&ba).value().sequence(5)
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
462
463
                .bind(1.333333333333f)
                .bind(PI)
464
                .bind(ascii)
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
465
466
467
468
                .bind(false)
                .bind(color)
                ;
        }
469
        STOP("Cbor",ba.toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
470
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
471
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
472
473
474
475
476
477
478
            QCborStreamWriter s(&b);
            s.startArray(5);
                s.append(1.333333333333f);
                s.append(PI);
                s.append(ascii);
                s.append(false);
                s.startMap();
479
                    s.append("RGB");s.startArray();
480
481
482
483
                        s.append(quint8(color.red  ()));
                        s.append(quint8(color.green()));
                        s.append(quint8(color.blue ()));
                        s.endArray();
484
                    s.append("base");s.append(quint8(255));
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
485
486
487
                    s.endMap();
                s.endArray();
        }
488
        STOP("QCborStream",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
489
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
490
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
491
492
493
494
495
496
497
498
499
            QDataStream d(&b);
            QDataWriter(&d).sequence()
                .bind(1.333333333333f)
                .bind(PI)
                .bind(ascii)
                .bind(false)
                .bind(color)
                ;
        }
500
        STOP("Data",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
501
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
502
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
503
504
505
506
507
508
509
            QDataStream(&b)
                    << 1.333333333333f
                    << PI
                    << ascii
                    << false
                    << color;
        }
510
        STOP("QDataStream",b.buffer().toHex());
511
512
        float f = 1.333333333333f; bool boolean = false;
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
513
514
            ba.resize(0);
            ba.append(reinterpret_cast<const char*>(&f      ),sizeof(f      )); // endianness must be specified externally
515
516
517
            ba.append(reinterpret_cast<const char*>(&PI     ),sizeof(PI     ));
            ba.append(                               ascii                   );
            ba.append(reinterpret_cast<const char*>(&boolean),sizeof(boolean));
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
518
            ba.append(reinterpret_cast<const char*>(&color  ),sizeof(color  )); // schema evolution must be specified externally
519
520
521
        }
        STOP("QByteArray",ba.toHex());

522
        QBindable bindables[5];
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
523
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
524
525
526
527
528
            bindables[0] = 1.333333333333f;
            bindables[1] = PI;
            bindables[2] = ascii;
            bindables[3] = false;
            bindables[4] = color;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
529
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
530
        STOP("Bindables","");
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
531
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
532
            ba.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
533
            QCborWriter(&ba).bind(bindables);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
534
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
535
        STOP("Bindables>Cbor",ba.toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
536
        START {
537
538
            ba.resize(0);
            QJsonWriter(&ba).bind(bindables);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
539
        }
540
        STOP("Bindables>Json",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
541
542
    }
    GROUP_STOP;
543
    GROUP("doubles>")//========================================================
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
544
545
    {
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
546
            s.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
547
548
549
550
551
552
553
            QDebug d(&s);
            for (int i=0; i < 16; i++) {
            d << transform[i];
            };
        }
        STOP("QDebug",s);
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
554
            ba.resize(0);
555
            TextWriter(&ba).bind(transform);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
556
        }
557
        STOP("Text",b.buffer());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
558
        START {
559
560
            ba.resize(0);
            QJsonWriter(&ba).bind(transform);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
561
        }
562
        STOP("Json",ba)
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
563
564
565
566
567
568
        START {
            ba.resize(0);
            QXmlStreamWriter w(&ba);
            QXmlWriter d(&w);
            d.bind(transform);
        }
569
        STOP("Xml",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
570
571
572
573
        START {
            v.clear();
            QVariantBuilder(&v).bind(transform);
        }
574
        STOP("Variant",Text(v).utf8());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
575
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
576
            b.seek(0); b.buffer().resize(0);
577
            QCborWriter(&ba).bind(transform);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
578
        }
579
        STOP("Cbor",ba.toHex());
580

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
581
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
582
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
583
            QCborStreamWriter s(&b);
584
            constexpr quint64 size = 16;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
585
586
            s.startArray(size);
                for (quint8 i=0; i < size; i++) {
587
                    s.append(transform[i]);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
588
589
590
                };
                s.endArray();
        }
591
        STOP("QCborStream",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
592
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
593
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
594
595
596
            QDataStream d(&b);
            QDataWriter(&d).value().bind(transform);
        }
597
        STOP("Data",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
598
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
599
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
600
601
            QDataStream data(&b);
            data << transform.size();
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
602
            for (int i=0; i < transform.size(); i++) {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
603
604
605
                data << transform[i];
            };
        }
606
        STOP("QDataStream",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
607
        QByteArray str; str.reserve(500);
608
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
609
610
            str.resize(0);
            int size=transform.size();
611
612
613
614
615
616
617
            str.append(reinterpret_cast<char*>(&size),sizeof(size));
            for (int i=0; i < size; i++) {
                str.append(reinterpret_cast<char*>(&transform[i]),sizeof(transform[i]));
            };
        }
        STOP("QByteArray",str.toHex());

618
        QBindable bindable;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
619
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
620
            bindable = transform;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
621
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
622
        STOP("Bindable","");
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
623
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
624
            ba.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
625
            QCborWriter(&ba).bind(bindable);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
626
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
627
        STOP("Bindable>Cbor",ba.toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
628
        START {
629
630
            ba.resize(0);
            QJsonWriter(&ba).bind(bindable);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
631
        }
632
        STOP("Bindable>Json",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
633
634
    }
    GROUP_STOP
635
    GROUP("Person>")//=========================================================
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
636
637
    {
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
638
            s.resize(0);
639
640
            QDebug dbg(&s);
            dbg << person;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
641
642
643
        }
        STOP("QDebug",s);
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
644
            ba.resize(0);
645
            TextWriter(&ba).bind(person);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
646
        }
647
        STOP("Text",b.buffer());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
648
        START {
649
650
            ba.resize(0);
            QJsonWriter(&ba).bind(person);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
651
        }
652
        STOP("Json",ba)
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
653
654
655
656
657
        START {
            ba.resize(0);
            QXmlStreamWriter w(&ba);
            QXmlWriter d(&w);
            d.bind(person);
658
            w.writeEndDocument(); // FIXME It should not be necessary
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
659
        }
660
        STOP("Xml",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
661
662
663
664
        START {
            v.clear();
            QVariantBuilder(&v).bind(person);
        }
665
        STOP("Variant",Text(v).utf8());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
666
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
667
            ba.resize(0);
668
            QCborWriter(&ba).bind(person);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
669
        }
670
        STOP("Cbor",ba.toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
671
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
672
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
673
674
675
676
677
678
            QCborStreamWriter s(&b);
            s.startMap();
                s.append("names");s.startArray();
                    s.append(person.firstName);
                    s.append(person. lastName);
                    s.endArray();
679
680
681
682
                s.append("height");s.append(person.height  );
                s.append("age"   );s.append(person.age     ); // or .any() to ignore
                int size = person.phones.size();
                s.append("phones");s.startArray(quint64(size));
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
683
                    for (int i=0; i < size; i++) {
684
                        s.startMap();
685
                            s.append("type"  );s.append(person.phones[i]._t);
686
687
                            s.append("number");s.append(person.phones[i]._n);
                            s.endMap();
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
688
                    }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
689
                    s.endArray();
690
691
692
                s.append("comments");s.append(person.comments);
                s.append("children");s.startArray(quint64(person.children.size()));
                    // Would need recursion
693
                    s.endArray();
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
694
695
            s.endMap();
        }
696
        STOP("QCborStream",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
697
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
698
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
699
700
701
            QDataStream d(&b);
            QDataWriter(&d).value().bind(person);
        }
702
        STOP("Data",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
703
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
704
            b.seek(0); b.buffer().resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
705
706
707
            QDataStream d(&b);
            d << person;
        }
708
        STOP("QDataStream",b.buffer().toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
709
        QByteArray str; str.reserve(100); int s;
710
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
711
            str.resize(0);
712
713
714
            str.append(reinterpret_cast<const char*>(person.firstName.constData()),person.firstName.size());// encoding must be specified externally
            str.append(reinterpret_cast<const char*>(person.lastName .constData()),person.lastName .size());
            str.append(reinterpret_cast<const char*>(&person.height),sizeof(person.height));                // endianness must be specified externally
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
715
            str.append(reinterpret_cast<const char*>(&person.age   ),sizeof(person.age   ));
716
717
718
719
720
721
722
723
724
725
726
            s=person.phones.size();
            str.append(reinterpret_cast<const char*>(&s),sizeof(s));
            for (int i=0; i<s; ++i) {
                str.append(reinterpret_cast<const char*>(&person.phones[i]._t),sizeof(person.phones[i]._t));str.append(person.phones[i]._n);
            }
            str.append(reinterpret_cast<const char*>(person.comments.constData()),person.comments.size());                                                           // byte order must be specified externally
            s=person.children.size();
            str.append(reinterpret_cast<const char*>(&s),sizeof(s));
            for (int i=0; i<s; ++i) {
                Q_ASSERT(false); // Would need recursion
            }
727
728
729
        }
        STOP("QByteArray",str.toHex());
#ifdef PROTOBUF
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
730
        std::string buf;
731
732
733
734
735
736
737
        pb::Person pb;
        pb.set_firstname("John");
        pb.set_lastname("Doe");
        pb.set_height(1.75);
        pb.set_age(18);
        pb.set_comments("unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ");
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
738
            buf.resize(0);
739
740
741
742
            buf = pb.SerializeAsString();
        }
        STOP("protobuf",QByteArray::fromStdString(buf).toHex());
#endif
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
        START {
            ba.resize(0);
            QJsonObject p{
                {"names"   , QJsonArray{person.firstName, person.lastName} },
                {"height"  , person.height},
                {"age"     , person.age},
                {"comments", person.comments},
                {"children", QJsonArray()}}; // would need recursion
            QJsonArray phones;
            for (auto&& phone : person.phones) {
                phones.append(QJsonObject{
                    {"type"  ,quint8(phone._t)},
                    {"number",       phone._n }});
            }
            p["phones"] = phones;
            ba = QJsonDocument(p).toJson(QJsonDocument::Compact);
        }
        STOP("QJsonDocument",ba)
761

762
        QBindable bindable;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
763
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
764
            bindable = person;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
765
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
766
        STOP("Bindable","");
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
767
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
768
            ba.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
769
            QCborWriter(&ba).bind(bindable);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
770
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
771
        STOP("Bindable>Cbor",ba.toHex());
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
772
        START {
773
774
            ba.resize(0);
            QJsonWriter(&ba).bind(bindable);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
775
        }
776
        STOP("Bindable>Json",ba);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
777
778
    }
    GROUP_STOP
779
780
781
782
783
784
785
786
787
788
789
790
    GROUP("Phone>")//=========================================================
    {
        START {
            s.resize(0);
            QDebug dbg(&s);
            dbg << phone;
        }
        STOP("QDebug",s);
        START {
            ba.resize(0);
            TextWriter(&ba).bind(phone);
        }
791
        STOP("Text",b.buffer());
792
        START {
793
794
            ba.resize(0);
            QJsonWriter(&ba).bind(phone);
795
        }
796
        STOP("Json",ba)
797
798
799
800
801
802
        START {
            ba.resize(0);
            QXmlStreamWriter w(&ba);
            QXmlWriter d(&w);
            d.bind(phone);
        }
803
        STOP("Xml",ba);
804
805
806
807
        START {
            v.clear();
            QVariantBuilder(&v).bind(phone);
        }
808
        STOP("Variant",Text(v).utf8());
809
810
811
812
        START {
            ba.resize(0);
            QCborWriter(&ba).bind(phone);
        }
813
        STOP("Cbor",ba.toHex());
814
815
816
817
818
819
820
821
        START {
            b.seek(0); b.buffer().resize(0);
            QCborStreamWriter s(&b);
            s.startMap();
                s.append("type"  );s.append(phone._t);
                s.append("number");s.append(phone._n);
                s.endMap();
        }
822
        STOP("QCborStream",b.buffer().toHex());
823
824
825
826
827
        START {
            b.seek(0); b.buffer().resize(0);
            QDataStream d(&b);
            QDataWriter(&d).value().bind(phone);
        }
828
        STOP("Data",b.buffer().toHex());
829
830
831
832
833
        START {
            b.seek(0); b.buffer().resize(0);
            QDataStream d(&b);
            d << phone;
        }
834
        STOP("QDataStream",b.buffer().toHex());
835
        QByteArray str; str.reserve(100);
836
837
838
839
840
841
        START {
            str.resize(0);
            str.append(reinterpret_cast<const char*>(&phone._t),sizeof(phone._t));str.append(phone._n);
        }
        STOP("QByteArray",str.toHex());

842
        QBindable bindable;
843
        START {
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
844
            bindable = phone;
845
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
846
        STOP("Bindable","");
847
848
        START {
            ba.resize(0);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
849
            QCborWriter(&ba).bind(bindable);
850
        }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
851
        STOP("Bindable>Cbor",ba.toHex());
852
        START {
853
854
            ba.resize(0);
            QJsonWriter(&ba).bind(bindable);
855
        }
856
        STOP("Bindable>Json",ba);
857
858
859
    }
    GROUP_STOP

860
    GROUP("Person<>Json")//====================================================
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
861
    {
862
        QBuffer json; json.open(QIODevice::ReadOnly);
863
864
        json.buffer() = "_{ \"names\": [ _\"John\" _, \"Doe\"] , \"age\"_:_null, \"height\":_1.75, \"phones\": [], \"_\":\"superfluous item\" _} ";
        //               1               15        23                   4042                58                                                102
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
865
        Person p;
866
867
868
869
870
        QBuffer roundtrip; roundtrip.open(QIODevice::ReadWrite);
        QJsonValue jv;
        QVector<QJsonReader ::Error>  readerErrors;
        QVector<QJsonVisitor::Error> visitorErrors;
        //---------------------------------------------------------------------
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
871
        START {
872
            json.seek(0); p = {};
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
873
            QJsonReader r(&json);
874
875
            r.bind(p);
            readerErrors = r.errors;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
876
        }
877
        STOP("Json>P",Text(p).utf8()+" | "+Text(readerErrors))
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
878
        START {
879
880
            roundtrip.seek(0);
            QJsonWriter(&roundtrip).bind(p);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
881
        }
EXT Arnaud Clère's avatar
merged  
EXT Arnaud Clère committed
882
        STOP("P>Json",QString(roundtrip.buffer()))
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
883
        START {
884
885
            roundtrip.seek(0); p = {};
            QJsonReader r(&roundtrip);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
886
            r.bind(p);
887
            readerErrors = r.errors;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
888
        }
889
        STOP("Json>P",Text(p).utf8()+" | "+Text(readerErrors))
890
        //---------------------------------------------------------------------
891
        START {
892
893
            jv = QJsonValue();
            QJsonBuilder(&jv).bind(p);
894
        }
895
        STOP("P>JsonValue",QJsonDocument(jv.toObject()).toJson(QJsonDocument::Compact));
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
896
897
        START {
            p = {};
898
            QJsonVisitor r(&jv);
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
899
            r.bind(p);
900
            visitorErrors = r.errors;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
901
        }
902
        STOP("JsonValue>P",Text(p).utf8()+" | "+Text(visitorErrors))
903
        //---------------------------------------------------------------------
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
904
        START {
905
            roundtrip.seek(0); jv = QJsonValue();
906
            QJsonReader r(&roundtrip);
907
            r.bind(jv);
908
909
            readerErrors = r.errors;
        }