Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
c772c01a
Unverified
Commit
c772c01a
authored
Jan 14, 2018
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
♻
refactored code to split headers
parent
1b54d4a5
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
671 additions
and
20 deletions
+671
-20
develop/detail/parsing/binary_reader.hpp
develop/detail/parsing/binary_reader.hpp
+270
-0
develop/detail/parsing/binary_writer.hpp
develop/detail/parsing/binary_writer.hpp
+367
-19
develop/json.hpp
develop/json.hpp
+33
-0
src/json.hpp
src/json.hpp
+1
-1
No files found.
develop/detail/parsing/binary_reader.hpp
View file @
c772c01a
...
@@ -90,6 +90,27 @@ class binary_reader
...
@@ -90,6 +90,27 @@ class binary_reader
return
res
;
return
res
;
}
}
/*!
@brief create a JSON value from UBJSON input
@param[in] strict whether to expect the input to be consumed completed
@return JSON value created from UBJSON input
@throw parse_error.110 if input ended unexpectedly or the end of file was
not reached when @a strict was set to true
@throw parse_error.112 if unsupported byte was read
*/
BasicJsonType
parse_ubjson
(
const
bool
strict
)
{
const
auto
res
=
parse_ubjson_internal
();
if
(
strict
)
{
get_ignore_noop
();
check_eof
(
true
);
}
return
res
;
}
/*!
/*!
@brief determine system byte order
@brief determine system byte order
...
@@ -751,6 +772,16 @@ class binary_reader
...
@@ -751,6 +772,16 @@ class binary_reader
}
}
}
}
/*!
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
*/
BasicJsonType
parse_ubjson_internal
(
const
bool
get_char
=
true
)
{
return
get_ubjson_value
(
get_char
?
get_ignore_noop
()
:
current
);
}
/*!
/*!
@brief get next character from the input
@brief get next character from the input
...
@@ -766,6 +797,20 @@ class binary_reader
...
@@ -766,6 +797,20 @@ class binary_reader
return
(
current
=
ia
->
get_character
());
return
(
current
=
ia
->
get_character
());
}
}
/*!
@return character read from the input after ignoring all 'N' entries
*/
int
get_ignore_noop
()
{
do
{
get
();
}
while
(
current
==
'N'
);
return
current
;
}
/*
/*
@brief read a number from the input
@brief read a number from the input
...
@@ -1051,6 +1096,231 @@ class binary_reader
...
@@ -1051,6 +1096,231 @@ class binary_reader
return
result
;
return
result
;
}
}
/*!
@brief reads a UBJSON string
This function is either called after reading the 'S' byte explicitly
indicating a string, or in case of an object key where the 'S' byte can be
left out.
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
@return string
@throw parse_error.110 if input ended
@throw parse_error.113 if an unexpected byte is read
*/
std
::
string
get_ubjson_string
(
const
bool
get_char
=
true
)
{
if
(
get_char
)
{
get
();
// TODO: may we ignore N here?
}
check_eof
();
switch
(
current
)
{
case
'U'
:
return
get_string
(
get_number
<
uint8_t
>
());
case
'i'
:
return
get_string
(
get_number
<
int8_t
>
());
case
'I'
:
return
get_string
(
get_number
<
int16_t
>
());
case
'l'
:
return
get_string
(
get_number
<
int32_t
>
());
case
'L'
:
return
get_string
(
get_number
<
int64_t
>
());
default:
std
::
stringstream
ss
;
ss
<<
std
::
setw
(
2
)
<<
std
::
uppercase
<<
std
::
setfill
(
'0'
)
<<
std
::
hex
<<
current
;
JSON_THROW
(
parse_error
::
create
(
113
,
chars_read
,
"expected a UBJSON string; last byte: 0x"
+
ss
.
str
()));
}
}
/*!
@brief determine the type and size for a container
In the optimized UBJSON format, a type and a size can be provided to allow
for a more compact representation.
@return pair of the size and the type
*/
std
::
pair
<
std
::
size_t
,
int
>
get_ubjson_size_type
()
{
std
::
size_t
sz
=
std
::
string
::
npos
;
int
tc
=
0
;
get_ignore_noop
();
if
(
current
==
'$'
)
{
tc
=
get
();
// must not ignore 'N', because 'N' maybe the type
check_eof
();
get_ignore_noop
();
if
(
current
!=
'#'
)
{
std
::
stringstream
ss
;
ss
<<
std
::
setw
(
2
)
<<
std
::
uppercase
<<
std
::
setfill
(
'0'
)
<<
std
::
hex
<<
current
;
JSON_THROW
(
parse_error
::
create
(
112
,
chars_read
,
"expected '#' after UBJSON type information; last byte: 0x"
+
ss
.
str
()));
}
sz
=
parse_ubjson_internal
();
}
else
if
(
current
==
'#'
)
{
sz
=
parse_ubjson_internal
();
}
return
std
::
make_pair
(
sz
,
tc
);
}
BasicJsonType
get_ubjson_value
(
const
int
prefix
)
{
switch
(
prefix
)
{
case
std
:
:
char_traits
<
char
>::
eof
()
:
// EOF
JSON_THROW
(
parse_error
::
create
(
110
,
chars_read
,
"unexpected end of input"
));
case
'T'
:
// true
return
true
;
case
'F'
:
// false
return
false
;
case
'Z'
:
// null
return
nullptr
;
case
'U'
:
return
get_number
<
uint8_t
>
();
case
'i'
:
return
get_number
<
int8_t
>
();
case
'I'
:
return
get_number
<
int16_t
>
();
case
'l'
:
return
get_number
<
int32_t
>
();
case
'L'
:
return
get_number
<
int64_t
>
();
case
'd'
:
return
get_number
<
float
>
();
case
'D'
:
return
get_number
<
double
>
();
case
'C'
:
// char
{
get
();
check_eof
();
if
(
JSON_UNLIKELY
(
not
(
0
<=
current
and
current
<=
127
)))
{
std
::
stringstream
ss
;
ss
<<
std
::
setw
(
2
)
<<
std
::
uppercase
<<
std
::
setfill
(
'0'
)
<<
std
::
hex
<<
current
;
JSON_THROW
(
parse_error
::
create
(
113
,
chars_read
,
"byte after 'C' must be in range 0x00..0x7F; last byte: 0x"
+
ss
.
str
()));
}
return
std
::
string
(
1
,
static_cast
<
char
>
(
current
));
}
case
'S'
:
// string
return
get_ubjson_string
();
case
'['
:
// array
return
get_ubjson_array
();
case
'{'
:
// object
return
get_ubjson_object
();
default:
// anything else
std
::
stringstream
ss
;
ss
<<
std
::
setw
(
2
)
<<
std
::
uppercase
<<
std
::
setfill
(
'0'
)
<<
std
::
hex
<<
current
;
JSON_THROW
(
parse_error
::
create
(
112
,
chars_read
,
"error reading UBJSON; last byte: 0x"
+
ss
.
str
()));
}
}
BasicJsonType
get_ubjson_array
()
{
BasicJsonType
result
=
value_t
::
array
;
const
auto
size_and_type
=
get_ubjson_size_type
();
if
(
size_and_type
.
first
!=
std
::
string
::
npos
)
{
if
(
size_and_type
.
second
!=
0
)
{
if
(
size_and_type
.
second
!=
'N'
)
std
::
generate_n
(
std
::
back_inserter
(
*
result
.
m_value
.
array
),
size_and_type
.
first
,
[
this
,
size_and_type
]()
{
return
get_ubjson_value
(
size_and_type
.
second
);
});
}
else
{
std
::
generate_n
(
std
::
back_inserter
(
*
result
.
m_value
.
array
),
size_and_type
.
first
,
[
this
]()
{
return
parse_ubjson_internal
();
});
}
}
else
{
while
(
current
!=
']'
)
{
result
.
push_back
(
parse_ubjson_internal
(
false
));
get_ignore_noop
();
}
}
return
result
;
}
BasicJsonType
get_ubjson_object
()
{
BasicJsonType
result
=
value_t
::
object
;
const
auto
size_and_type
=
get_ubjson_size_type
();
if
(
size_and_type
.
first
!=
std
::
string
::
npos
)
{
if
(
size_and_type
.
second
!=
0
)
{
if
(
size_and_type
.
second
!=
'N'
)
std
::
generate_n
(
std
::
inserter
(
*
result
.
m_value
.
object
,
result
.
m_value
.
object
->
end
()),
size_and_type
.
first
,
[
this
,
size_and_type
]()
{
auto
key
=
get_ubjson_string
();
auto
val
=
get_ubjson_value
(
size_and_type
.
second
);
return
std
::
make_pair
(
std
::
move
(
key
),
std
::
move
(
val
));
});
}
else
{
std
::
generate_n
(
std
::
inserter
(
*
result
.
m_value
.
object
,
result
.
m_value
.
object
->
end
()),
size_and_type
.
first
,
[
this
]()
{
auto
key
=
get_ubjson_string
();
auto
val
=
parse_ubjson_internal
();
return
std
::
make_pair
(
std
::
move
(
key
),
std
::
move
(
val
));
});
}
}
else
{
while
(
current
!=
'}'
)
{
auto
key
=
get_ubjson_string
(
false
);
result
[
std
::
move
(
key
)]
=
parse_ubjson_internal
();
get_ignore_noop
();
}
}
return
result
;
}
/*!
/*!
@brief check if input ended
@brief check if input ended
@throw parse_error.110 if input ended
@throw parse_error.110 if input ended
...
...
develop/detail/parsing/binary_writer.hpp
View file @
c772c01a
This diff is collapsed.
Click to expand it.
develop/json.hpp
View file @
c772c01a
...
@@ -6630,6 +6630,26 @@ class basic_json
...
@@ -6630,6 +6630,26 @@ class basic_json
binary_writer
<
char
>
(
o
).
write_msgpack
(
j
);
binary_writer
<
char
>
(
o
).
write_msgpack
(
j
);
}
}
static
std
::
vector
<
uint8_t
>
to_ubjson
(
const
basic_json
&
j
,
const
bool
use_size
=
false
,
const
bool
use_type
=
false
)
{
std
::
vector
<
uint8_t
>
result
;
to_ubjson
(
j
,
result
,
use_size
,
use_type
);
return
result
;
}
static
void
to_ubjson
(
const
basic_json
&
j
,
detail
::
output_adapter
<
uint8_t
>
o
,
const
bool
use_size
=
false
,
const
bool
use_type
=
false
)
{
binary_writer
<
uint8_t
>
(
o
).
write_ubjson
(
j
,
use_size
,
use_type
);
}
static
void
to_ubjson
(
const
basic_json
&
j
,
detail
::
output_adapter
<
char
>
o
,
const
bool
use_size
=
false
,
const
bool
use_type
=
false
)
{
binary_writer
<
char
>
(
o
).
write_ubjson
(
j
,
use_size
,
use_type
);
}
/*!
/*!
@brief create a JSON value from an input in CBOR format
@brief create a JSON value from an input in CBOR format
...
@@ -6824,6 +6844,19 @@ class basic_json
...
@@ -6824,6 +6844,19 @@ class basic_json
return
binary_reader
(
detail
::
input_adapter
(
std
::
forward
<
A1
>
(
a1
),
std
::
forward
<
A2
>
(
a2
))).
parse_msgpack
(
strict
);
return
binary_reader
(
detail
::
input_adapter
(
std
::
forward
<
A1
>
(
a1
),
std
::
forward
<
A2
>
(
a2
))).
parse_msgpack
(
strict
);
}
}
static
basic_json
from_ubjson
(
detail
::
input_adapter
i
,
const
bool
strict
=
true
)
{
return
binary_reader
(
i
).
parse_ubjson
(
strict
);
}
template
<
typename
A1
,
typename
A2
,
detail
::
enable_if_t
<
std
::
is_constructible
<
detail
::
input_adapter
,
A1
,
A2
>
::
value
,
int
>
=
0
>
static
basic_json
from_ubjson
(
A1
&&
a1
,
A2
&&
a2
,
const
bool
strict
=
true
)
{
return
binary_reader
(
detail
::
input_adapter
(
std
::
forward
<
A1
>
(
a1
),
std
::
forward
<
A2
>
(
a2
))).
parse_ubjson
(
strict
);
}
/// @}
/// @}
//////////////////////////
//////////////////////////
...
...
src/json.hpp
View file @
c772c01a
...
@@ -6409,7 +6409,7 @@ class binary_writer
...
@@ -6409,7 +6409,7 @@ class binary_writer
write_number
(
static_cast
<
uint32_t
>
(
N
));
write_number
(
static_cast
<
uint32_t
>
(
N
));
}
}
// LCOV_EXCL_START
// LCOV_EXCL_START
else
if
(
N
<=
(
std
::
numeric_limits
<
uint
32
_t
>::
max
)())
else
if
(
N
<=
(
std
::
numeric_limits
<
uint
64
_t
>::
max
)())
{
{
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBB
));
oa
->
write_character
(
static_cast
<
CharType
>
(
0xBB
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
write_number
(
static_cast
<
uint64_t
>
(
N
));
...
...
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