Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
c117515e
Unverified
Commit
c117515e
authored
Aug 14, 2017
by
Théo DELRIEU
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add detail/parsing/binary_writer.hpp
parent
d620f76f
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
561 additions
and
540 deletions
+561
-540
Makefile
Makefile
+2
-1
binary_writer.hpp
src/detail/parsing/binary_writer.hpp
+558
-0
json.hpp
src/json.hpp
+1
-539
No files found.
Makefile
View file @
c117515e
...
@@ -19,7 +19,8 @@ SRCS = ${SRCDIR}/json.hpp \
...
@@ -19,7 +19,8 @@ SRCS = ${SRCDIR}/json.hpp \
${
SRCDIR
}
/detail/iterators/iteration_proxy.hpp
\
${
SRCDIR
}
/detail/iterators/iteration_proxy.hpp
\
${
SRCDIR
}
/detail/iterators/json_reverse_iterator.hpp
\
${
SRCDIR
}
/detail/iterators/json_reverse_iterator.hpp
\
${
SRCDIR
}
/detail/parsing/output_adapters.hpp
\
${
SRCDIR
}
/detail/parsing/output_adapters.hpp
\
${
SRCDIR
}
/detail/parsing/binary_reader.hpp
${
SRCDIR
}
/detail/parsing/binary_reader.hpp
\
${
SRCDIR
}
/detail/parsing/binary_writer.hpp
# main target
# main target
all
:
all
:
...
...
src/detail/parsing/binary_writer.hpp
0 → 100644
View file @
c117515e
#ifndef NLOHMANN_JSON_DETAIL_PARSING_BINARY_WRITER_HPP
#define NLOHMANN_JSON_DETAIL_PARSING_BINARY_WRITER_HPP
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
#include <limits>
#include "detail/parsing/binary_reader.hpp"
#include "detail/parsing/output_adapters.hpp"
namespace
nlohmann
{
namespace
detail
{
///////////////////
// binary writer //
///////////////////
/*!
@brief serialization to CBOR and MessagePack values
*/
template
<
typename
BasicJsonType
,
typename
CharType
>
class
binary_writer
{
public
:
/*!
@brief create a binary writer
@param[in] adapter output adapter to write to
*/
explicit
binary_writer
(
output_adapter_t
<
CharType
>
adapter
)
:
oa
(
adapter
)
{
assert
(
oa
);
}
/*!
@brief[in] j JSON value to serialize
*/
void
write_cbor
(
const
BasicJsonType
&
j
)
{
switch
(
j
.
type
())
{
case
value_t
:
:
null
:
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xF6
));
break
;
}
case
value_t
:
:
boolean
:
{
oa
->
write_character
(
j
.
m_value
.
boolean
?
static_cast
<
CharType
>
(
0xF5
)
:
static_cast
<
CharType
>
(
0xF4
));
break
;
}
case
value_t
:
:
number_integer
:
{
if
(
j
.
m_value
.
number_integer
>=
0
)
{
// CBOR does not differentiate between positive signed
// integers and unsigned integers. Therefore, we used the
// code from the value_t::number_unsigned case here.
if
(
j
.
m_value
.
number_integer
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x18
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x19
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1A
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1B
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
}
else
{
// The conversions below encode the sign in the first
// byte, and the value is converted to a positive number.
const
auto
positive_number
=
-
1
-
j
.
m_value
.
number_integer
;
if
(
j
.
m_value
.
number_integer
>=
-
24
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x20
+
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x38
));
write_number
(
static_cast
<
uint8_t
>
(
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x39
));
write_number
(
static_cast
<
uint16_t
>
(
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x3A
));
write_number
(
static_cast
<
uint32_t
>
(
positive_number
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x3B
));
write_number
(
static_cast
<
uint64_t
>
(
positive_number
));
}
}
break
;
}
case
value_t
:
:
number_unsigned
:
{
if
(
j
.
m_value
.
number_unsigned
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x18
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x19
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1A
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1B
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_unsigned
));
}
break
;
}
case
value_t
:
:
number_float
:
// Double-Precision Float
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xFB
));
write_number
(
j
.
m_value
.
number_float
);
break
;
}
case
value_t
:
:
string
:
{
// step 1: write control byte and the string length
const
auto
N
=
j
.
m_value
.
string
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x60
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x78
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x79
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x7A
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x7B
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write the string
oa
->
write_characters
(
reinterpret_cast
<
const
CharType
*>
(
j
.
m_value
.
string
->
c_str
()),
j
.
m_value
.
string
->
size
());
break
;
}
case
value_t
:
:
array
:
{
// step 1: write control byte and the array size
const
auto
N
=
j
.
m_value
.
array
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x80
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x98
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x99
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x9A
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x9B
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
array
)
{
write_cbor
(
el
);
}
break
;
}
case
value_t
:
:
object
:
{
// step 1: write control byte and the object size
const
auto
N
=
j
.
m_value
.
object
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0xA0
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xB8
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xB9
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBA
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBB
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
object
)
{
write_cbor
(
el
.
first
);
write_cbor
(
el
.
second
);
}
break
;
}
default
:
break
;
}
}
/*!
@brief[in] j JSON value to serialize
*/
void
write_msgpack
(
const
BasicJsonType
&
j
)
{
switch
(
j
.
type
())
{
case
value_t
:
:
null
:
// nil
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xC0
));
break
;
}
case
value_t
:
:
boolean
:
// true and false
{
oa
->
write_character
(
j
.
m_value
.
boolean
?
static_cast
<
CharType
>
(
0xC3
)
:
static_cast
<
CharType
>
(
0xC2
));
break
;
}
case
value_t
:
:
number_integer
:
{
if
(
j
.
m_value
.
number_integer
>=
0
)
{
// MessagePack does not differentiate between positive
// signed integers and unsigned integers. Therefore, we used
// the code from the value_t::number_unsigned case here.
if
(
j
.
m_value
.
number_unsigned
<
128
)
{
// positive fixnum
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
// uint 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCC
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
// uint 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCD
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
// uint 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCE
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint64_t
>::
max
)())
{
// uint 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCF
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
}
else
{
if
(
j
.
m_value
.
number_integer
>=
-
32
)
{
// negative fixnum
write_number
(
static_cast
<
int8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int8_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int8_t
>::
max
)())
{
// int 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD0
));
write_number
(
static_cast
<
int8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int16_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int16_t
>::
max
)())
{
// int 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD1
));
write_number
(
static_cast
<
int16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int32_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int32_t
>::
max
)())
{
// int 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD2
));
write_number
(
static_cast
<
int32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int64_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int64_t
>::
max
)())
{
// int 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD3
));
write_number
(
static_cast
<
int64_t
>
(
j
.
m_value
.
number_integer
));
}
}
break
;
}
case
value_t
:
:
number_unsigned
:
{
if
(
j
.
m_value
.
number_unsigned
<
128
)
{
// positive fixnum
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
// uint 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCC
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
// uint 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCD
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
// uint 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCE
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint64_t
>::
max
)())
{
// uint 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCF
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
break
;
}
case
value_t
:
:
number_float
:
// float 64
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCB
));
write_number
(
j
.
m_value
.
number_float
);
break
;
}
case
value_t
:
:
string
:
{
// step 1: write control byte and the string length
const
auto
N
=
j
.
m_value
.
string
->
size
();
if
(
N
<=
31
)
{
// fixstr
write_number
(
static_cast
<
uint8_t
>
(
0xA0
|
N
));
}
else
if
(
N
<=
255
)
{
// str 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD9
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
65535
)
{
// str 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDA
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
4294967295
)
{
// str 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDB
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write the string
oa
->
write_characters
(
reinterpret_cast
<
const
CharType
*>
(
j
.
m_value
.
string
->
c_str
()),
j
.
m_value
.
string
->
size
());
break
;
}
case
value_t
:
:
array
:
{
// step 1: write control byte and the array size
const
auto
N
=
j
.
m_value
.
array
->
size
();
if
(
N
<=
15
)
{
// fixarray
write_number
(
static_cast
<
uint8_t
>
(
0x90
|
N
));
}
else
if
(
N
<=
0xFFFF
)
{
// array 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDC
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
// array 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDD
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
array
)
{
write_msgpack
(
el
);
}
break
;
}
case
value_t
:
:
object
:
{
// step 1: write control byte and the object size
const
auto
N
=
j
.
m_value
.
object
->
size
();
if
(
N
<=
15
)
{
// fixmap
write_number
(
static_cast
<
uint8_t
>
(
0x80
|
(
N
&
0xF
)));
}
else
if
(
N
<=
65535
)
{
// map 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDE
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
4294967295
)
{
// map 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDF
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
object
)
{
write_msgpack
(
el
.
first
);
write_msgpack
(
el
.
second
);
}
break
;
}
default
:
break
;
}
}
private
:
/*
@brief write a number to output input
@param[in] n number of type @a NumberType
@tparam NumberType the type of the number
@note This function needs to respect the system's endianess, because bytes
in CBOR and MessagePack are stored in network order (big endian) and
therefore need reordering on little endian systems.
*/
template
<
typename
NumberType
>
void
write_number
(
NumberType
n
)
{
// step 1: write number to array of length NumberType
std
::
array
<
CharType
,
sizeof
(
NumberType
)
>
vec
;
std
::
memcpy
(
vec
.
data
(),
&
n
,
sizeof
(
NumberType
));
// step 2: write array to output (with possible reordering)
if
(
is_little_endian
)
{
// reverse byte order prior to conversion if necessary
std
::
reverse
(
vec
.
begin
(),
vec
.
end
());
}
oa
->
write_characters
(
vec
.
data
(),
sizeof
(
NumberType
));
}
private
:
/// whether we can assume little endianess
const
bool
is_little_endian
=
binary_reader
<
BasicJsonType
>::
little_endianess
();
/// the output
output_adapter_t
<
CharType
>
oa
=
nullptr
;
};
}
}
#endif
src/json.hpp
View file @
c117515e
...
@@ -67,6 +67,7 @@ SOFTWARE.
...
@@ -67,6 +67,7 @@ SOFTWARE.
#include "detail/iterators/json_reverse_iterator.hpp"
#include "detail/iterators/json_reverse_iterator.hpp"
#include "detail/parsing/output_adapters.hpp"
#include "detail/parsing/output_adapters.hpp"
#include "detail/parsing/binary_reader.hpp"
#include "detail/parsing/binary_reader.hpp"
#include "detail/parsing/binary_writer.hpp"
/*!
/*!
@brief namespace for Niels Lohmann
@brief namespace for Niels Lohmann
...
@@ -78,545 +79,6 @@ namespace nlohmann
...
@@ -78,545 +79,6 @@ namespace nlohmann
namespace
detail
namespace
detail
{
{
///////////////////
///////////////////
// binary writer //
///////////////////
/*!
@brief serialization to CBOR and MessagePack values
*/
template
<
typename
BasicJsonType
,
typename
CharType
>
class
binary_writer
{
public
:
/*!
@brief create a binary writer
@param[in] adapter output adapter to write to
*/
explicit
binary_writer
(
output_adapter_t
<
CharType
>
adapter
)
:
oa
(
adapter
)
{
assert
(
oa
);
}
/*!
@brief[in] j JSON value to serialize
*/
void
write_cbor
(
const
BasicJsonType
&
j
)
{
switch
(
j
.
type
())
{
case
value_t
:
:
null
:
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xF6
));
break
;
}
case
value_t
:
:
boolean
:
{
oa
->
write_character
(
j
.
m_value
.
boolean
?
static_cast
<
CharType
>
(
0xF5
)
:
static_cast
<
CharType
>
(
0xF4
));
break
;
}
case
value_t
:
:
number_integer
:
{
if
(
j
.
m_value
.
number_integer
>=
0
)
{
// CBOR does not differentiate between positive signed
// integers and unsigned integers. Therefore, we used the
// code from the value_t::number_unsigned case here.
if
(
j
.
m_value
.
number_integer
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x18
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x19
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1A
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1B
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
}
else
{
// The conversions below encode the sign in the first
// byte, and the value is converted to a positive number.
const
auto
positive_number
=
-
1
-
j
.
m_value
.
number_integer
;
if
(
j
.
m_value
.
number_integer
>=
-
24
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x20
+
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x38
));
write_number
(
static_cast
<
uint8_t
>
(
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x39
));
write_number
(
static_cast
<
uint16_t
>
(
positive_number
));
}
else
if
(
positive_number
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x3A
));
write_number
(
static_cast
<
uint32_t
>
(
positive_number
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x3B
));
write_number
(
static_cast
<
uint64_t
>
(
positive_number
));
}
}
break
;
}
case
value_t
:
:
number_unsigned
:
{
if
(
j
.
m_value
.
number_unsigned
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x18
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x19
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1A
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_unsigned
));
}
else
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x1B
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_unsigned
));
}
break
;
}
case
value_t
:
:
number_float
:
// Double-Precision Float
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xFB
));
write_number
(
j
.
m_value
.
number_float
);
break
;
}
case
value_t
:
:
string
:
{
// step 1: write control byte and the string length
const
auto
N
=
j
.
m_value
.
string
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x60
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x78
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x79
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x7A
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x7B
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write the string
oa
->
write_characters
(
reinterpret_cast
<
const
CharType
*>
(
j
.
m_value
.
string
->
c_str
()),
j
.
m_value
.
string
->
size
());
break
;
}
case
value_t
:
:
array
:
{
// step 1: write control byte and the array size
const
auto
N
=
j
.
m_value
.
array
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0x80
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x98
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x99
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x9A
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0x9B
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
array
)
{
write_cbor
(
el
);
}
break
;
}
case
value_t
:
:
object
:
{
// step 1: write control byte and the object size
const
auto
N
=
j
.
m_value
.
object
->
size
();
if
(
N
<=
0x17
)
{
write_number
(
static_cast
<
uint8_t
>
(
0xA0
+
N
));
}
else
if
(
N
<=
0xFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xB8
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
0xFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xB9
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBA
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// LCOV_EXCL_START
else
if
(
N
<=
0xFFFFFFFFFFFFFFFF
)
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBB
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
}
// LCOV_EXCL_STOP
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
object
)
{
write_cbor
(
el
.
first
);
write_cbor
(
el
.
second
);
}
break
;
}
default
:
break
;
}
}
/*!
@brief[in] j JSON value to serialize
*/
void
write_msgpack
(
const
BasicJsonType
&
j
)
{
switch
(
j
.
type
())
{
case
value_t
:
:
null
:
// nil
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xC0
));
break
;
}
case
value_t
:
:
boolean
:
// true and false
{
oa
->
write_character
(
j
.
m_value
.
boolean
?
static_cast
<
CharType
>
(
0xC3
)
:
static_cast
<
CharType
>
(
0xC2
));
break
;
}
case
value_t
:
:
number_integer
:
{
if
(
j
.
m_value
.
number_integer
>=
0
)
{
// MessagePack does not differentiate between positive
// signed integers and unsigned integers. Therefore, we used
// the code from the value_t::number_unsigned case here.
if
(
j
.
m_value
.
number_unsigned
<
128
)
{
// positive fixnum
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
// uint 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCC
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
// uint 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCD
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
// uint 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCE
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint64_t
>::
max
)())
{
// uint 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCF
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
}
else
{
if
(
j
.
m_value
.
number_integer
>=
-
32
)
{
// negative fixnum
write_number
(
static_cast
<
int8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int8_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int8_t
>::
max
)())
{
// int 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD0
));
write_number
(
static_cast
<
int8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int16_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int16_t
>::
max
)())
{
// int 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD1
));
write_number
(
static_cast
<
int16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int32_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int32_t
>::
max
)())
{
// int 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD2
));
write_number
(
static_cast
<
int32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_integer
>=
(
std
::
numeric_limits
<
int64_t
>::
min
)()
and
j
.
m_value
.
number_integer
<=
(
std
::
numeric_limits
<
int64_t
>::
max
)())
{
// int 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD3
));
write_number
(
static_cast
<
int64_t
>
(
j
.
m_value
.
number_integer
));
}
}
break
;
}
case
value_t
:
:
number_unsigned
:
{
if
(
j
.
m_value
.
number_unsigned
<
128
)
{
// positive fixnum
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint8_t
>::
max
)())
{
// uint 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCC
));
write_number
(
static_cast
<
uint8_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint16_t
>::
max
)())
{
// uint 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCD
));
write_number
(
static_cast
<
uint16_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint32_t
>::
max
)())
{
// uint 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCE
));
write_number
(
static_cast
<
uint32_t
>
(
j
.
m_value
.
number_integer
));
}
else
if
(
j
.
m_value
.
number_unsigned
<=
(
std
::
numeric_limits
<
uint64_t
>::
max
)())
{
// uint 64
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCF
));
write_number
(
static_cast
<
uint64_t
>
(
j
.
m_value
.
number_integer
));
}
break
;
}
case
value_t
:
:
number_float
:
// float 64
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xCB
));
write_number
(
j
.
m_value
.
number_float
);
break
;
}
case
value_t
:
:
string
:
{
// step 1: write control byte and the string length
const
auto
N
=
j
.
m_value
.
string
->
size
();
if
(
N
<=
31
)
{
// fixstr
write_number
(
static_cast
<
uint8_t
>
(
0xA0
|
N
));
}
else
if
(
N
<=
255
)
{
// str 8
oa
->
write_character
(
static_cast
<
CharType
>
(
0xD9
));
write_number
(
static_cast
<
uint8_t
>
(
N
));
}
else
if
(
N
<=
65535
)
{
// str 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDA
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
4294967295
)
{
// str 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDB
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write the string
oa
->
write_characters
(
reinterpret_cast
<
const
CharType
*>
(
j
.
m_value
.
string
->
c_str
()),
j
.
m_value
.
string
->
size
());
break
;
}
case
value_t
:
:
array
:
{
// step 1: write control byte and the array size
const
auto
N
=
j
.
m_value
.
array
->
size
();
if
(
N
<=
15
)
{
// fixarray
write_number
(
static_cast
<
uint8_t
>
(
0x90
|
N
));
}
else
if
(
N
<=
0xFFFF
)
{
// array 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDC
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
0xFFFFFFFF
)
{
// array 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDD
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
array
)
{
write_msgpack
(
el
);
}
break
;
}
case
value_t
:
:
object
:
{
// step 1: write control byte and the object size
const
auto
N
=
j
.
m_value
.
object
->
size
();
if
(
N
<=
15
)
{
// fixmap
write_number
(
static_cast
<
uint8_t
>
(
0x80
|
(
N
&
0xF
)));
}
else
if
(
N
<=
65535
)
{
// map 16
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDE
));
write_number
(
static_cast
<
uint16_t
>
(
N
));
}
else
if
(
N
<=
4294967295
)
{
// map 32
oa
->
write_character
(
static_cast
<
CharType
>
(
0xDF
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
// step 2: write each element
for
(
const
auto
&
el
:
*
j
.
m_value
.
object
)
{
write_msgpack
(
el
.
first
);
write_msgpack
(
el
.
second
);
}
break
;
}
default
:
break
;
}
}
private
:
/*
@brief write a number to output input
@param[in] n number of type @a NumberType
@tparam NumberType the type of the number
@note This function needs to respect the system's endianess, because bytes
in CBOR and MessagePack are stored in network order (big endian) and
therefore need reordering on little endian systems.
*/
template
<
typename
NumberType
>
void
write_number
(
NumberType
n
)
{
// step 1: write number to array of length NumberType
std
::
array
<
CharType
,
sizeof
(
NumberType
)
>
vec
;
std
::
memcpy
(
vec
.
data
(),
&
n
,
sizeof
(
NumberType
));
// step 2: write array to output (with possible reordering)
if
(
is_little_endian
)
{
// reverse byte order prior to conversion if necessary
std
::
reverse
(
vec
.
begin
(),
vec
.
end
());
}
oa
->
write_characters
(
vec
.
data
(),
sizeof
(
NumberType
));
}
private
:
/// whether we can assume little endianess
const
bool
is_little_endian
=
binary_reader
<
BasicJsonType
>::
little_endianess
();
/// the output
output_adapter_t
<
CharType
>
oa
=
nullptr
;
};
///////////////////
// serialization //
// serialization //
///////////////////
///////////////////
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment