Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
MODMED
modmedLog
Commits
f781b951
Commit
f781b951
authored
Mar 22, 2019
by
EXT Arnaud Clère
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Cbor support and tests
parent
c4ab7ec5
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
588 additions
and
334 deletions
+588
-334
tests/QBind/QBind_impl.h
tests/QBind/QBind_impl.h
+2
-0
tests/QBind/QCbor_impl.h
tests/QBind/QCbor_impl.h
+169
-11
tests/QBind/QJson_impl.h
tests/QBind/QJson_impl.h
+1
-1
tests/QBind/QVariant_impl.h
tests/QBind/QVariant_impl.h
+222
-190
tests/QBind/main.cpp
tests/QBind/main.cpp
+194
-132
No files found.
tests/QBind/QBind_impl.h
View file @
f781b951
...
...
@@ -62,6 +62,8 @@ public:
QUtf8String
(
const
QByteArray
&
o
)
:
QByteArray
(
o
)
{}
QUtf8String
()
:
QByteArray
()
{}
};
#include <QtCore/qmetatype.h>
Q_DECLARE_METATYPE
(
QUtf8String
)
using
QName
=
const
char
*
;
//!< String literal explicitely utf8 encoded
...
...
tests/QBind/QCbor_impl.h
View file @
f781b951
...
...
@@ -176,7 +176,6 @@ private:
};
// --------------------------------------------------------------------------
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
#include <QtCore/qcborstream.h>
#include <QtCore/qstack.h>
...
...
@@ -331,14 +330,14 @@ public:
/**/
Seq
<
Cursor
>
sequence
(
quint32
*
s
=
nullptr
)
{
return
Cursor
(
this
).
value
().
sequence
(
s
);
}
template
<
typename
T
>
Cursor
bind
(
T
&&
t
)
{
return
Cursor
(
this
).
value
().
bind
(
std
::
forward
<
T
>
(
t
));
}
protected:
bool
_sequence
(
quint32
*
s
=
nullptr
)
{
Q_UNUSED
(
s
);
levels
.
push
(
Step
(
nullptr
));
return
true
;
}
bool
_record
(
quint32
*
s
=
nullptr
)
{
Q_UNUSED
(
s
);
levels
.
push
(
Step
(
""
));
return
true
;
}
bool
_null
(
)
{
set
(
QCborValue
(
));
return
true
;
}
bool
_bind
(
const
char
*
s
)
{
set
(
QCborValue
(
s
));
return
true
;
}
bool
_bind
(
bool
&
b
)
{
set
(
QCborValue
(
b
));
return
true
;
}
bool
_bind
(
double
&
d
)
{
set
(
QCborValue
(
d
));
return
true
;
}
bool
_bind
(
quint64
&
n
)
{
double
d
(
n
);
return
_bind
(
d
);
}
bool
_bind
(
qint64
&
n
)
{
double
d
(
n
);
return
_bind
(
d
);
}
bool
_sequence
(
quint32
*
=
nullptr
)
{
levels
.
push
(
Step
(
nullptr
));
return
true
;
}
bool
_record
(
quint32
*
=
nullptr
)
{
levels
.
push
(
Step
(
""
));
return
true
;
}
bool
_null
(
)
{
set
(
QCborValue
(
));
return
true
;
}
bool
_bind
(
const
char
*
s
)
{
set
(
QCborValue
(
s
));
return
true
;
}
bool
_bind
(
bool
&
b
)
{
set
(
QCborValue
(
b
));
return
true
;
}
bool
_bind
(
double
&
d
)
{
set
(
QCborValue
(
d
));
return
true
;
}
bool
_bind
(
quint64
&
n
)
{
double
d
(
n
);
return
_bind
(
d
);
}
bool
_bind
(
qint64
&
n
)
{
double
d
(
n
);
return
_bind
(
d
);
}
bool
_item
(
QName
n
)
{
levels
.
last
().
key
=
n
;
return
true
;
}
bool
_item
(
)
{
levels
.
last
().
key
=
nullptr
;
return
true
;
}
...
...
@@ -358,7 +357,166 @@ private:
QCborValue
*
cbor
;
struct
Step
{
QUtf8String
key
;
/* TODO union */
QCborMap
object
;
QCborArray
array
;
Step
(
const
char
*
k
=
nullptr
)
:
key
(
k
)
{}
};
QStack
<
Step
>
levels
=
QStack
<
Step
>
();
//!< minimal dynamic context to implement out() and ensure actual building in case QCborBuilder
Impl
is abandoned
QStack
<
Step
>
levels
=
QStack
<
Step
>
();
//!< minimal dynamic context to implement out() and ensure actual building in case QCborBuilder is abandoned
};
#endif
#include <QtCore/qvector.h>
class
QCborVisitor
:
public
IReader
{
Q_DISABLE_COPY
(
QCborVisitor
)
public:
QCborVisitor
(
const
QCborValue
*
v
)
:
cbor
(
v
)
{
Q_ASSERT
(
v
);
}
struct
Step
{
const
char
*
key
=
nullptr
;
int
idx
=-
1
;
QCborValue
item
;
Step
()
=
default
;
};
struct
Error
{
const
char
*
error
;
QUtf8String
path
;
template
<
class
T
>
T
bind
(
Val
<
T
>&&
value
)
{
return
value
.
bind
(
QUtf8String
(
error
)
+
' '
+
path
);
}
};
QVector
<
Error
>
errors
;
QUtf8String
currentPath
()
{
QUtf8String
path
;
Q_FOREACH
(
Step
s
,
steps
)
{
if
(
s
.
key
)
{
path
.
append
(
'{'
).
append
(
s
.
key
);
}
else
{
path
.
append
(
'['
).
append
(
QUtf8String
::
number
(
s
.
idx
));
}
}
return
path
;
}
// Shortcuts
/**/
Val
<
Cursor
>
value
(
)
{
return
Cursor
(
this
).
value
();
}
/**/
Seq
<
Cursor
>
sequence
(
quint32
*
s
=
nullptr
)
{
return
Cursor
(
this
).
value
().
sequence
(
s
);
}
template
<
typename
T
>
Cursor
bind
(
T
&&
t
)
{
return
Cursor
(
this
).
value
().
bind
(
std
::
forward
<
T
>
(
t
));
}
protected:
bool
_sequence
(
quint32
*
=
nullptr
)
{
if
(
current
()
->
isArray
())
{
steps
.
push
(
Step
());
return
true
;
}
_reportError
(
qBindExpectedSequence
);
return
false
;
}
bool
_record
(
quint32
*
=
nullptr
)
{
if
(
current
()
->
isMap
())
{
steps
.
push
(
Step
());
return
true
;
}
_reportError
(
qBindExpectedRecord
);
return
false
;
}
bool
_null
(
)
{
if
(
current
()
->
isNull
())
{
return
true
;
}
_reportError
(
qBindExpectedNull
);
return
false
;
}
bool
_bind
(
QUtf8String
&
u
)
{
QString
s
;
if
(
_bind
(
s
)
)
{
u
=
s
.
toUtf8
()
;
return
true
;
}
return
false
;
}
bool
_bind
(
QString
&
v
)
{
if
(
current
()
->
isString
())
{
v
=
current
()
->
toString
();
return
true
;
}
_reportError
(
qBindExpectedText
);
return
false
;
}
bool
_bind
(
QByteArray
&
v
)
{
if
(
current
()
->
isByteArray
())
{
v
=
current
()
->
toByteArray
();
return
true
;
}
_reportError
(
qBindExpectedText
);
return
false
;
}
bool
_bind
(
bool
&
v
)
{
if
(
current
()
->
isBool
())
{
v
=
current
()
->
toBool
();
return
true
;
}
_reportError
(
qBindExpectedBoolean
);
return
false
;
}
bool
_bind
(
qint64
&
t
)
{
if
(
current
()
->
isInteger
())
{
t
=
current
()
->
toInteger
();
return
true
;
}
return
false
;
}
bool
_bind
(
quint64
&
t
)
{
if
(
current
()
->
isInteger
())
{
t
=
current
()
->
toInteger
();
return
true
;
}
return
false
;
}
// TODO full quint64 range
bool
_bind
(
float
&
v
)
{
double
d
;
if
(
_bind
(
d
)
)
{
v
=
float
(
d
)
;
return
true
;
}
return
false
;
}
bool
_bind
(
double
&
v
)
{
if
(
current
()
->
isDouble
())
{
v
=
current
()
->
toDouble
();
return
true
;
}
_reportError
(
qBindExpectedDecimal
);
return
false
;
}
bool
_item
(
QUtf8String
&
k
)
{
steps
.
last
().
key
=
k
;
return
!
(
steps
.
last
().
item
=
current
(
1
)
->
toMap
().
value
(
QString
::
fromUtf8
(
steps
.
last
().
key
))).
isUndefined
();
}
bool
_item
(
)
{
steps
.
last
().
idx
++
;
return
!
(
steps
.
last
().
item
=
current
(
1
)
->
toArray
().
at
(
steps
.
last
().
idx
)).
isUndefined
();
}
bool
_out
(
)
{
steps
.
pop
()
;
return
true
;
}
bool
_isOk
()
{
return
true
;
}
void
_setChoice
(
bool
v
)
{
isChoice
=
v
;
}
void
_reportError
(
const
char
*
e
)
{
if
(
!
isChoice
)
errors
.
append
(
Error
{
e
,
currentPath
()
});
}
private:
const
QCborValue
*
current
(
unsigned
outer
=
0
)
const
{
return
unsigned
(
steps
.
size
())
-
outer
<=
0
?
cbor
:
&
(
steps
[
unsigned
(
steps
.
size
())
-
outer
-
1
].
item
);
}
const
QCborValue
*
cbor
;
QStack
<
Step
>
steps
=
QStack
<
Step
>
();
bool
isChoice
=
false
;
};
// //////////////////////////////////////////////////////////////////////////
// QBind<QCbor*,_> support
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
template
<
class
TResult
>
//=Cursor
struct
QBind
<
QCborValue
,
TResult
>
{
static
TResult
bind
(
Val
<
TResult
>&&
v
,
QCborValue
&&
j
)
{
if
(
v
->
mode
()
==
Write
)
{
if
(
j
.
isMap
())
return
v
.
bind
(
j
.
toMap
());
if
(
j
.
isArray
())
return
v
.
bind
(
j
.
toArray
());
if
(
j
.
isBool
())
return
v
.
bind
(
j
.
toBool
());
if
(
j
.
isInteger
())
return
v
.
bind
(
j
.
toInteger
());
if
(
j
.
isDouble
())
return
v
.
bind
(
j
.
toDouble
());
if
(
j
.
isString
())
return
v
.
bind
(
j
.
toString
());
if
(
j
.
isByteArray
())
return
v
.
bind
(
j
.
toByteArray
());
return
v
.
null
();
}
else
{
Q_ASSERT_X
(
false
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
static
TResult
bind
(
Val
<
TResult
>&&
v
,
QCborValue
&
j
)
{
if
(
v
->
mode
()
==
Write
)
{
return
bind
(
std
::
move
(
v
),
std
::
move
(
j
));
}
else
if
(
v
->
mode
()
==
Read
)
{
TResult
r
;
{
QScopedChoice
<
Val
<
TResult
>>
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
;
}
bool
b
;
if
((
r
=
v
.
bind
(
b
)))
{
j
=
QCborValue
(
b
);
return
r
;
}
qint64
i
;
if
((
r
=
v
.
bind
(
i
)))
{
j
=
QCborValue
(
i
);
return
r
;
}
quint64
u
;
if
((
r
=
v
.
bind
(
u
)))
{
j
=
QCborValue
(
double
(
u
));
return
r
;
}
// FIXME range
double
d
;
if
((
r
=
v
.
bind
(
d
)))
{
j
=
QCborValue
(
d
);
return
r
;
}
QByteArray
y
;
if
((
r
=
v
.
bind
(
y
)))
{
j
=
QCborValue
(
y
);
return
r
;
}
}
if
(
!
(
r
=
v
.
null
()))
r
.
reportError
(
"Expected bool|double|QString|QCborArray|QCborOnject|null"
);
/**/
j
=
QCborValue
(
);
return
r
;
}
else
{
Q_ASSERT_X
(
!
v
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
};
template
<
class
TResult
>
//=Cursor
struct
QBind
<
QCborArray
,
TResult
>
{
static
TResult
bind
(
Val
<
TResult
>&&
v
,
QCborArray
&&
j
)
{
if
(
v
->
mode
()
==
Write
)
{
quint32
size
=
quint32
(
j
.
size
());
auto
s
(
v
.
sequence
(
&
size
));
for
(
QCborValue
item
:
j
)
{
s
=
s
.
bind
(
item
);
}
return
s
;
}
else
{
Q_ASSERT_X
(
false
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
static
TResult
bind
(
Val
<
TResult
>&&
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
;
while
((
i
=
s
.
item
()))
{
QCborValue
json
;
if
((
s
=
i
.
bind
(
json
)))
j
.
append
(
json
);
}
return
s
;
}
else
{
Q_ASSERT_X
(
!
v
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
};
template
<
class
TResult
>
//=Cursor
struct
QBind
<
QCborMap
,
TResult
>
{
static
TResult
bind
(
Val
<
TResult
>&&
v
,
QCborMap
&&
j
)
{
if
(
v
->
mode
()
==
Write
)
{
quint32
size
=
quint32
(
j
.
size
());
auto
s
(
v
.
record
(
&
size
));
for
(
QCborValue
key
:
j
.
keys
())
{
s
=
s
.
bind
(
key
.
toString
().
toUtf8
().
constData
(),
QCborValue
(
j
[
key
]));
}
return
s
;
}
else
{
Q_ASSERT_X
(
false
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
static
TResult
bind
(
Val
<
TResult
>&&
v
,
QCborMap
&
j
)
{
if
(
v
->
mode
()
==
Write
)
{
return
bind
(
std
::
move
(
v
),
std
::
move
(
j
));
}
else
if
(
v
->
mode
()
==
Read
)
{
auto
s
(
v
.
record
());
QUtf8String
k
;
Val
<
Rec
<
TResult
>>
i
;
while
((
i
=
s
.
item
(
k
)))
{
QCborValue
json
;
if
((
s
=
i
.
bind
(
json
)))
j
.
insert
(
QString
::
fromUtf8
(
k
),
json
);
}
return
s
;
}
else
{
Q_ASSERT_X
(
!
v
,
Q_FUNC_INFO
,
"Unsupported v->mode()"
);
return
v
.
null
();
}
}
};
tests/QBind/QJson_impl.h
View file @
f781b951
...
...
@@ -92,7 +92,7 @@ private:
QJsonValue
*
json
;
struct
Step
{
QUtf8String
key
;
/* TODO union */
QJsonObject
object
;
QJsonArray
array
;
Step
(
const
char
*
k
=
nullptr
)
:
key
(
k
)
{}
};
QStack
<
Step
>
steps
=
QStack
<
Step
>
();
//!< minimal dynamic context to implement out() and ensure actual building in case QJsonBuilder
Impl
is abandoned
QStack
<
Step
>
steps
=
QStack
<
Step
>
();
//!< minimal dynamic context to implement out() and ensure actual building in case QJsonBuilder is abandoned
};
// --------------------------------------------------------------------------
...
...
tests/QBind/QVariant_impl.h
View file @
f781b951
This diff is collapsed.
Click to expand it.
tests/QBind/main.cpp
View file @
f781b951
...
...
@@ -155,9 +155,8 @@ public:
#include <QtCore/qdebug.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsondocument.h>
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
#include <QtCore/qcborstream.h>
#endif
#include <QtGui/qcolor.h>
// NB: It is not possible to use QBENCHMARK to evaluate qDebug because it installs a specific handler
...
...
@@ -169,7 +168,7 @@ public:
groupWarmup=(previousTotal<0.01 || std::abs(groupTotal-previousTotal)*100/previousTotal > 1.); \
previousTotal=groupTotal; \
groupTotal=0.; \
if (previousTotal<0.01) { fprintf(results,"group "); fprintf(samples, "group |%s\n", group); } else fprintf(results,"%-1
0
s",group);
if (previousTotal<0.01) { fprintf(results,"group
"); fprintf(samples, "group |%s\n", group); } else fprintf(results,"%-1
2
s",group);
#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); \
...
...
@@ -203,11 +202,10 @@ int main(int argc, char *argv[])
// Temporary buffers
QString
s
;
QBuffer
b
;
QBuffer
b
;
b
.
open
(
QIODevice
::
ReadWrite
);
QVariant
v
;
b
.
open
(
QIODevice
::
ReadWrite
);
QDataStream
d
(
&
b
);
GROUP
(
"
<
builtin"
)
GROUP
(
"builtin
>
"
)
//========================================================
{
START
{
s
.
clear
();
...
...
@@ -264,7 +262,6 @@ int main(int argc, char *argv[])
;
}
STOP
(
"Cbor"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborStreamWriter
s
(
&
b
);
...
...
@@ -282,7 +279,6 @@ int main(int argc, char *argv[])
s
.
endArray
();
}
STOP
(
"QCborStream"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#endif
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QDataStream
d
(
&
b
);
...
...
@@ -326,7 +322,7 @@ int main(int argc, char *argv[])
STOP
(
"Writables>Json"
,
QString
::
fromUtf8
(
b
.
buffer
()));
}
GROUP_STOP
;
GROUP
(
"
<
doubles"
)
GROUP
(
"doubles
>
"
)
//========================================================
{
START
{
s
.
clear
();
...
...
@@ -356,7 +352,7 @@ int main(int argc, char *argv[])
QCborWriter
(
&
b
).
bind
(
transform
);
}
STOP
(
"Cbor"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborStreamWriter
s
(
&
b
);
...
...
@@ -368,7 +364,6 @@ int main(int argc, char *argv[])
s
.
endArray
();
}
STOP
(
"QCborStream"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#endif
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QDataStream
d
(
&
b
);
...
...
@@ -401,7 +396,7 @@ int main(int argc, char *argv[])
STOP
(
"Writable>Json"
,
QString
::
fromUtf8
(
b
.
buffer
()));
}
GROUP_STOP
GROUP
(
"
<
Person"
)
GROUP
(
"Person
>
"
)
//=========================================================
{
START
{
s
.
clear
();
...
...
@@ -434,7 +429,7 @@ int main(int argc, char *argv[])
QCborWriter
(
&
b
).
bind
(
person
);
}
STOP
(
"Cbor"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborStreamWriter
s
(
&
b
);
...
...
@@ -456,7 +451,6 @@ int main(int argc, char *argv[])
s
.
endMap
();
}
STOP
(
"QCborStream"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()));
#endif
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QDataStream
d
(
&
b
);
...
...
@@ -486,151 +480,219 @@ int main(int argc, char *argv[])
STOP
(
"Writable>Json"
,
QString
::
fromUtf8
(
b
.
buffer
()));
}
GROUP_STOP
GROUP
(
"
Read+Write"
)
GROUP
(
"
Person<>Json"
)
//====================================================
{
QBuffer
json
;
json
.
open
(
QIODevice
::
ReadOnly
);
json
.
buffer
()
=
"_{
\"
names
\"
: [ _
\"
John
\"
_,
\"
Doe
\"
] ,
\"
age
\"
_:_null,
\"
height
\"
:_1.75,
\"
phones
\"
: [
\"
+44 1234567
\"
,
\"
+44 2345678
\"
],
\"\"
:
\"
superfluous item
\"
_} "
;
// 0 22 41 55 70
QJsonValue
v
;
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
QCborValue
c
;
#endif
QBuffer
json
;
json
.
open
(
QIODevice
::
ReadOnly
);
json
.
buffer
()
=
"_{
\"
names
\"
: [ _
\"
John
\"
_,
\"
Doe
\"
] ,
\"
age
\"
_:_null,
\"
height
\"
:_1.75,
\"
phones
\"
: [
\"
+44 1234567
\"
,
\"
+44 2345678
\"
],
\"\"
:
\"
superfluous item
\"
_} "
;
Person
p
;
QVector
<
QJsonReader
::
Error
>
jsonReaderErrors
;
QBuffer
roundtrip
;
roundtrip
.
open
(
QIODevice
::
ReadWrite
);
QJsonValue
jv
;
QCborValue
cv
;
QVector
<
QJsonReader
::
Error
>
readerErrors
;
QVector
<
QJsonVisitor
::
Error
>
visitorErrors
;
//---------------------------------------------------------------------
START
{
json
.
seek
(
0
);
b
.
seek
(
0
);
b
.
buffer
().
clear
()
;
json
.
seek
(
0
);
p
=
{}
;
QJsonReader
r
(
&
json
);
r
.
bind
(
QCborWriter
(
&
b
).
value
()
);
jsonR
eaderErrors
=
r
.
errors
;
r
.
bind
(
p
);
r
eaderErrors
=
r
.
errors
;
}
STOP
(
"Json>
Cbor
"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
(
)))
STOP
(
"Json>
P
"
,
QString
::
fromUtf8
(
Text
(
p
)
+
Text
(
readerErrors
)))
START
{
json
.
seek
(
0
);
v
=
QJsonValue
();
QJsonReader
r
(
&
json
);
r
.
bind
(
v
);
jsonReaderErrors
=
r
.
errors
;
roundtrip
.
seek
(
0
);
QJsonWriter
(
&
roundtrip
).
bind
(
p
);
}
STOP
(
"
Json
>Json
Value
"
,
QString
::
fromUtf8
(
QJsonDocument
(
v
.
toObject
()).
toJson
()
+
Text
(
jsonReaderErrors
)))
;
STOP
(
"
P
>Json"
,
QString
::
fromUtf8
(
roundtrip
.
buffer
(
)))
START
{
json
.
seek
(
0
);
p
=
{};
QJsonReader
r
(
&
json
);
roundtrip
.
seek
(
0
);
p
=
{};
QJsonReader
r
(
&
roundtrip
);
r
.
bind
(
p
);
jsonR
eaderErrors
=
r
.
errors
;
r
eaderErrors
=
r
.
errors
;
}
STOP
(
"Json>T"
,
QString
::
fromUtf8
(
Text
(
p
)
+
Text
(
jsonReaderErrors
)))
QBuffer
roundtripJson
;
roundtripJson
.
open
(
QIODevice
::
ReadWrite
);
STOP
(
"Json>P"
,
QString
::
fromUtf8
(
Text
(
p
)
+
Text
(
readerErrors
)))
//---------------------------------------------------------------------
START
{
roundtripJson
.
seek
(
0
);
QJson
Writer
(
&
roundtripJson
).
bind
(
p
);
jv
=
QJsonValue
(
);
QJson
Builder
(
&
jv
).
bind
(
p
);
}
STOP
(
"T>Json"
,
QString
::
fromUtf8
(
roundtripJson
.
buffer
()))
START
{
v
=
QJsonValue
();
QJsonBuilder
(
&
v
).
bind
(
p
);
}
STOP
(
"T>JsonValue"
,
QString
::
fromUtf8
(
QJsonDocument
(
v
.
toObject
()).
toJson
()));
QVector
<
QJsonVisitor
::
Error
>
jsonVisitorErrors
;
STOP
(
"P>JsonValue"
,
QString
::
fromUtf8
(
QJsonDocument
(
jv
.
toObject
()).
toJson
()));
START
{
p
=
{};
QJsonVisitor
r
(
&
v
);
QJsonVisitor
r
(
&
j
v
);
r
.
bind
(
p
);
jsonV
isitorErrors
=
r
.
errors
;
v
isitorErrors
=
r
.
errors
;
}
STOP
(
"JsonValue>T"
,
QString
::
fromUtf8
(
Text
(
p
)
+
Text
(
jsonVisitorErrors
)))
STOP
(
"JsonValue>P"
,
QString
::
fromUtf8
(
Text
(
p
)
+
Text
(
visitorErrors
)))
//---------------------------------------------------------------------
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborWriter
(
&
b
).
bind
(
p
);
roundtrip
.
seek
(
0
);
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QJsonReader
r
(
&
roundtrip
);
r
.
bind
(
QCborWriter
(
&
b
).
value
());
readerErrors
=
r
.
errors
;
}
STOP
(
"Json>Cbor"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()))
START
{
roundtrip
.
seek
(
0
);
jv
=
QJsonValue
();
QJsonReader
r
(
&
roundtrip
);
r
.
bind
(
jv
);
readerErrors
=
r
.
errors
;
}
STOP
(
"T>Cbor"
,
QString
::
fromUtf8
(
b
.
buffer
().
toHex
()))
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
QCborStreamReader
r
(
b
.
buffer
());
STOP
(
"Json>JsonValue"
,
QString
::
fromUtf8
(
QJsonDocument
(
jv
.
toObject
()).
toJson
()
+
Text
(
readerErrors
)));
}
GROUP_STOP
GROUP
(
"Person<>Cbor"
)
//====================================================
{
QBuffer
cbor
;
cbor
.
open
(
QIODevice
::
ReadOnly
);
cbor
.
buffer
()
=
QByteArray
::
fromHex
(
QByteArray
(
"A5"
// map(5)
"65"
"6E616D6573"
// text(5) "names"
"82"
// array(2)
"64"
"4A6F686E"
// text(4) "John"
"63"
"446F65"
// text(3) "Doe"
"63"
"616765"
// text(3) "age"
"12"
// unsigned(18)
"66"
"686569676874"
// text(6) "height"
"F6"
// primitive(22)
"66"
"70686F6E6573"
// text(6) "phones"
"82"
// array(2)
"6B"
"2B34342031323334353637"
// text(11) "+44 1234567"
"6B"
"2B34342032333435363738"
// text(11) "+44 2345678"
"60"
// text(0) ""
"70"
"7375706572666C756F7573206974656D"
// text(16) "superfluous item"
));
Person
p
;
QBuffer
roundtrip
;
roundtrip
.
open
(
QIODevice
::
ReadWrite
);
QJsonValue
jv
;
QCborValue
cv
;
QVector
<
QCborReader
::
Error
>
readerErrors
;
QVector
<
QCborVisitor
::
Error
>
visitorErrors
;
QCborStreamReader
reader
(
cbor
.
buffer
());
bool
parsed
;
//---------------------------------------------------------------------
START
{
p
=
{};
r
.
reset
();
if
(
r
.
isMap
()
&&
r
.
enterContainer
()
&&
r
.
hasNext
()
&&
r
.
isString
()
&&
r
.
readString
().
data
==
"names"
&&
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
r
.
isArray
()
&&
r
.
enterContainer
()
&&
r
.
hasNext
()
&&
r
.
isString
())
p
.
firstName
=
r
.
readString
().
data
;
if
(
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
r
.
hasNext
()
&&
r
.
isString
())
p
.
lastName
=
r
.
readString
().
data
;
if
(
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
!
r
.
hasNext
()
&&
r
.
leaveContainer
()
&&
r
.
hasNext
()
&&
r
.
isString
()
&&
r
.
readString
().
data
==
"height"
&&
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
r
.
isDouble
())
p
.
height
=
r
.
toDouble
();
if
(
r
.
next
()
&&
r
.
hasNext
()
&&
r
.
isString
()
&&
r
.
readString
().
data
==
"age"
&&
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
!
r
.
isUnsignedInteger
()
&&
r
.
isNegativeInteger
())
p
.
age
=
int
(
r
.
toInteger
());
if
(
r
.
next
()
&&
r
.
hasNext
()
&&
r
.
isString
()
&&
r
.
readString
().
data
==
"phones"
&&
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
r
.
isArray
()
&&
r
.
enterContainer
()
&&
r
.
hasNext
()
&&
r
.
isString
())
p
.
phones
.
append
(
r
.
readString
().
data
);
if
(
//r.readString().status==QCborStreamReader::EndOfString &&
r
.
hasNext
()
&&
r
.
isString
())
p
.
phones
.
append
(
r
.
readString
().
data
);
if
(
//r.readString().status==QCborStreamReader::EndOfString &&
!
r
.
hasNext
()
&&
r
.
leaveContainer
()
&&
r
.
hasNext
()
&&
r
.
isString
()
&&
r
.
readString
().
data
==
"comments"
&&
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
r
.
isString
())
p
.
comments
=
r
.
readString
().
data
;
parsed
=
r
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
!
r
.
hasNext
()
&&
r
.
leaveContainer
();
r
.
reset
();
reader
.
reset
();
p
=
{};
QCborReader
r
(
&
reader
);
r
.
bind
(
p
);
readerErrors
=
r
.
errors
;
}
STOP
(
"
Q
Cbor
Stream>T
"
,
QString
(
Text
(
p
)
+
Text
(
parsed
)))
STOP
(
"Cbor
>P
"
,
QString
(
Text
(
p
)
+
Text
(
readerErrors
)))
START
{
p
=
{};
r
.
reset
();
QCborReader
(
&
r
).
bind
(
p
);
roundtrip
.
seek
(
0
);
QCborWriter
(
&
roundtrip
).
bind
(
p
);
}
STOP
(
"Cbor
>T
"
,
QString
(
Text
(
p
)
/*+Text(jsonVisitorErrors)*/
))
STOP
(
"
P>
Cbor"
,
QString
::
fromUtf8
(
roundtrip
.
buffer
().
toHex
()
))
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborBuilder
(
&
c
).
bind
(
p
);
roundtrip
.
seek
(
0
);
reader
.
setDevice
(
&
roundtrip
);
p
=
{};
QCborReader
r
(
&
reader
);
r
.
bind
(
p
);
readerErrors
=
r
.
errors
;
}
STOP
(
"
T>
Cbor
Value
"
,
QString
::
fromUtf8
(
c
.
toCbor
().
toHex
(
)))
#endif
STOP
(
"Cbor
>P
"
,
QString
(
Text
(
p
)
+
Text
(
readerErrors
)))
//---------------------------------------------------------------------
START
{
b
.
seek
(
0
);
b
.
buffer
().
clear
();
QCborWriter
(
&
b
).
bind
(
v
);
p
=
{};
reader
.
reset
();
if
(
reader
.
isMap
()
&&
reader
.
enterContainer
()
&&
reader
.
hasNext
()
&&
reader
.
isString
()
&&
reader
.
readString
().
data
==
"names"
&&
reader
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
reader
.
isArray
()
&&
reader
.
enterContainer
()
&&
reader
.
hasNext
()
&&
reader
.
isString
())
p
.
firstName
=
reader
.
readString
().
data
;
if
(
reader
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
reader
.
hasNext
()
&&
reader
.
isString
())
p
.
lastName
=
reader
.
readString
().
data
;
if
(
reader
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
!
reader
.
hasNext
()
&&
reader
.
leaveContainer
()
&&
reader
.
hasNext
()
&&
reader
.
isString
()
&&
reader
.
readString
().
data
==
"height"
&&
reader
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
reader
.
isDouble
())
p
.
height
=
reader
.
toDouble
();
if
(
reader
.
next
()
&&
reader
.
hasNext
()
&&
reader
.
isString
()
&&
reader
.
readString
().
data
==
"age"
&&
reader
.
readString
().
status
==
QCborStreamReader
::
EndOfString
&&
!
reader
.
isUnsignedInteger
()
&&