Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
MODMED
modmedLog
Commits
f781b951
Commit
f781b951
authored
Mar 22, 2019
by
EXT Arnaud Clère
Browse files
Added Cbor support and tests
parent
c4ab7ec5
Changes
5
Show whitespace changes
Inline
Side-by-side
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,8 +330,8 @@ 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
_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
;
}
...
...
@@ -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
...
...
@@ -53,6 +53,7 @@ class QVariantBuilder : public IWriter
public:
QVariantBuilder
(
QVariant
*
v
)
:
variant
(
v
)
{
Q_ASSERT
(
v
);
}
~
QVariantBuilder
()
{
while
(
!
levels
.
isEmpty
())
_out
();
}
void
reset
(
QVariant
*
v
)
{
variant
=
v
;
Q_ASSERT
(
v
);
levels
.
clear
();
}
// Shortcuts
/**/
Val
<
Cursor
>
value
(
)
{
return
Cursor
(
this
).
value
();
}
...
...
@@ -98,6 +99,7 @@ class QVariantVisitor : public IReader
public:
Q_ENABLE_MOVE_DEFAULT
(
QVariantVisitor
)
QVariantVisitor
(
const
QVariant
*
v
)
:
value
(
v
)
{
Q_ASSERT
(
v
);
}
void
reset
(
const
QVariant
*
v
)
{
value
=
v
;
Q_ASSERT
(
v
);
levels
.
clear
();
errors
.
clear
();
}
struct
Error
{
const
char
*
error
;
QUtf8String
path
;
template
<
class
T
>
T
bind
(
Val
<
T
>&&
value
)
{
return
value
.
bind
(
QUtf8String
(
error
)
+
' '
+
path
);
}
};
QVector
<
Error
>
errors
;
...
...
@@ -114,7 +116,37 @@ protected:
// TODO Support _meta to be able to cache and restitute all metadata as well as data+datatype
template
<
typename
T
>
bool
_bind
(
T
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
T
>
())
{
t
=
current
()
->
value
<
T
>
();
return
true
;
}
_reportError
(
"Expected T"
);
return
false
;
}
bool
_bind
(
T
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
T
>
())
{
t
=
current
()
->
value
<
T
>
();
return
true
;
}
_reportError
(
"Expected declared metatype T"
);
return
false
;
}
bool
_bind
(
QUtf8String
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
QUtf8String
>
())
{
t
=
current
()
->
value
<
QUtf8String
>
();
return
true
;
}
_reportError
(
qBindExpectedText
);
return
false
;
}
bool
_bind
(
QString
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
QString
>
())
{
t
=
current
()
->
value
<
QString
>
();
return
true
;
}
_reportError
(
qBindExpectedText
);
return
false
;
}
bool
_bind
(
bool
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
bool
>
())
{
t
=
current
()
->
value
<
bool
>
();
return
true
;
}
_reportError
(
qBindExpectedBoolean
);
return
false
;
}
bool
_bind
(
QByteArray
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
QByteArray
>
())
{
t
=
current
()
->
value
<
QByteArray
>
();
return
true
;
}
_reportError
(
qBindExpectedBytes
);
return
false
;
}
// Convert numerical types to strictly larger ones // TODO convert all compatible values
bool
_bind
(
qint8
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
qint8
>
())
{
t
=
current
()
->
value
<
qint8
>
();
return
true
;
}
_reportError
(
qBindExpectedInteger
);
return
false
;
}
bool
_bind
(
qint16
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
qint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint16
>
())
{
t
=
current
()
->
value
<
qint16
>
();
return
true
;
}
_reportError
(
qBindExpectedInteger
);
return
false
;
}
bool
_bind
(
qint32
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
qint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint16
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint32
>
())
{
t
=
current
()
->
value
<
qint32
>
();
return
true
;
}
_reportError
(
qBindExpectedInteger
);
return
false
;
}
bool
_bind
(
qint64
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
qint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint16
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint32
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
qint64
>
())
{
t
=
current
()
->
value
<
qint64
>
();
return
true
;
}
_reportError
(
qBindExpectedInteger
);
return
false
;
}
bool
_bind
(
quint8
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
quint8
>
())
{
t
=
current
()
->
value
<
quint8
>
();
return
true
;
}
_reportError
(
qBindExpectedPositiveNumber
);
return
false
;
}
bool
_bind
(
quint16
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
quint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint16
>
())
{
t
=
current
()
->
value
<
quint16
>
();
return
true
;
}
_reportError
(
qBindExpectedPositiveNumber
);
return
false
;
}
bool
_bind
(
quint32
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
quint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint16
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint32
>
())
{
t
=
current
()
->
value
<
quint32
>
();
return
true
;
}
_reportError
(
qBindExpectedPositiveNumber
);
return
false
;
}
bool
_bind
(
quint64
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
quint8
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint16
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint32
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
quint64
>
())
{
t
=
current
()
->
value
<
quint64
>
();
return
true
;
}
_reportError
(
qBindExpectedPositiveNumber
);
return
false
;
}
bool
_bind
(
float
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
float
>
())
{
t
=
current
()
->
value
<
float
>
();
return
true
;
}
_reportError
(
qBindExpectedDecimal
);
return
false
;
}
bool
_bind
(
double
&
t
)
{
if
(
current
()
->
type
()
==
qMetaTypeId
<
float
>
()
||
current
()
->
type
()
==
qMetaTypeId
<
double
>
())
{
t
=
current
()
->
value
<
double
>
();
return
true
;
}
_reportError
(
qBindExpectedDecimal
);
return
false
;
}
bool
_sequence
(
quint32
*
=
nullptr
)
{
if
(
current
()
->
type
()
==
QVariant
::
List
)
{
levels
.
push
(
Level
());
return
true
;
}
_reportError
(
qBindExpectedSequence
);
return
false
;
}
bool
_record
(
quint32
*
=
nullptr
)
{
if
(
current
()
->
type
()
==
QVariant
::
Map
)
{
levels
.
push
(
Level
());
return
true
;
}
_reportError
(
qBindExpectedRecord
);
return
false
;
}
bool
_null
(
)
{
if
(
current
()
->
isNull
()
)
{
return
true
;
}
_reportError
(
qBindExpectedNull
);
return
false
;
}
...
...
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
();