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
850671b9
Unverified
Commit
850671b9
authored
7 years ago
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
using a vector<bool> for the parser hierarchy
parent
5f723bbe
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
152 additions
and
166 deletions
+152
-166
include/nlohmann/detail/input/parser.hpp
include/nlohmann/detail/input/parser.hpp
+76
-83
single_include/nlohmann/json.hpp
single_include/nlohmann/json.hpp
+76
-83
No files found.
include/nlohmann/detail/input/parser.hpp
View file @
850671b9
...
@@ -162,10 +162,9 @@ class parser
...
@@ -162,10 +162,9 @@ class parser
private:
private:
bool
sax_parse_internal
(
json_sax_t
*
sax
)
bool
sax_parse_internal
(
json_sax_t
*
sax
)
{
{
// two values for the structured values
enum
class
parse_state_t
{
array_value
,
object_value
};
// stack to remember the hieararchy of structured values we are parsing
// stack to remember the hieararchy of structured values we are parsing
std
::
vector
<
parse_state_t
>
states
;
// true = array; false = object
std
::
vector
<
bool
>
states
;
// value to avoid a goto (see comment where set to true)
// value to avoid a goto (see comment where set to true)
bool
skip_to_state_evaluation
=
false
;
bool
skip_to_state_evaluation
=
false
;
...
@@ -221,7 +220,7 @@ class parser
...
@@ -221,7 +220,7 @@ class parser
}
}
// remember we are now inside an object
// remember we are now inside an object
states
.
push_back
(
parse_state_t
::
object_valu
e
);
states
.
push_back
(
fals
e
);
// parse values
// parse values
get_token
();
get_token
();
...
@@ -249,7 +248,7 @@ class parser
...
@@ -249,7 +248,7 @@ class parser
}
}
// remember we are now inside an array
// remember we are now inside an array
states
.
push_back
(
parse_state_t
::
array_val
ue
);
states
.
push_back
(
tr
ue
);
// parse values (no need to call get_token)
// parse values (no need to call get_token)
continue
;
continue
;
...
@@ -359,104 +358,98 @@ class parser
...
@@ -359,104 +358,98 @@ class parser
else
else
{
{
get_token
();
get_token
();
switch
(
states
.
back
())
if
(
states
.
back
())
// array
{
{
case
parse_state_t
:
:
array_value
:
// comma -> next value
if
(
last_token
==
token_type
::
value_separator
)
{
{
// comma -> next value
// parse a new value
if
(
last_token
==
token_type
::
value_separator
)
get_token
();
continue
;
}
// closing ]
if
(
JSON_LIKELY
(
last_token
==
token_type
::
end_array
))
{
if
(
JSON_UNLIKELY
(
not
sax
->
end_array
()))
{
{
// parse a new value
return
false
;
get_token
();
continue
;
}
}
// closing ]
// We are done with this array. Before we can parse a
if
(
JSON_LIKELY
(
last_token
==
token_type
::
end_array
))
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert
(
not
states
.
empty
());
states
.
pop_back
();
skip_to_state_evaluation
=
true
;
continue
;
}
else
{
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
end_array
)));
}
}
else
// object
{
// comma -> next value
if
(
last_token
==
token_type
::
value_separator
)
{
get_token
();
// parse key
if
(
JSON_UNLIKELY
(
last_token
!=
token_type
::
value_string
))
{
{
if
(
JSON_UNLIKELY
(
not
sax
->
end_array
()))
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
value_string
)));
}
else
{
if
(
JSON_UNLIKELY
(
not
sax
->
key
(
m_lexer
.
get_string
())))
{
{
return
false
;
return
false
;
}
}
// We are done with this array. Before we can parse
// a new value, we need to evaluate the new state
// first. By setting skip_to_state_evaluation to
// false, we are effectively jumping to the
// beginning of this switch.
assert
(
not
states
.
empty
());
states
.
pop_back
();
skip_to_state_evaluation
=
true
;
continue
;
}
}
else
// parse separator (:)
get_token
();
if
(
JSON_UNLIKELY
(
last_token
!=
token_type
::
name_separator
))
{
{
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
end_array
)));
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
name_separator
)));
}
}
// parse values
get_token
();
continue
;
}
}
case
parse_state_t
:
:
object_value
:
// closing }
if
(
JSON_LIKELY
(
last_token
==
token_type
::
end_object
))
{
{
// comma -> next value
if
(
JSON_UNLIKELY
(
not
sax
->
end_object
()))
if
(
last_token
==
token_type
::
value_separator
)
{
{
get_token
();
return
false
;
// parse key
if
(
JSON_UNLIKELY
(
last_token
!=
token_type
::
value_string
))
{
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
value_string
)));
}
else
{
if
(
JSON_UNLIKELY
(
not
sax
->
key
(
m_lexer
.
get_string
())))
{
return
false
;
}
}
// parse separator (:)
get_token
();
if
(
JSON_UNLIKELY
(
last_token
!=
token_type
::
name_separator
))
{
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
name_separator
)));
}
// parse values
get_token
();
continue
;
}
}
// closing }
// We are done with this object. Before we can parse a
if
(
JSON_LIKELY
(
last_token
==
token_type
::
end_object
))
// new value, we need to evaluate the new state first.
{
// By setting skip_to_state_evaluation to false, we
if
(
JSON_UNLIKELY
(
not
sax
->
end_object
()))
// are effectively jumping to the beginning of this if.
{
assert
(
not
states
.
empty
());
return
false
;
states
.
pop_back
();
}
skip_to_state_evaluation
=
true
;
continue
;
// We are done with this object. Before we can
}
// parse a new value, we need to evaluate the new
else
// state first. By setting skip_to_state_evaluation
{
// to false, we are effectively jumping to the
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
// beginning of this switch.
m_lexer
.
get_token_string
(),
assert
(
not
states
.
empty
());
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
end_object
)));
states
.
pop_back
();
skip_to_state_evaluation
=
true
;
continue
;
}
else
{
return
sax
->
parse_error
(
m_lexer
.
get_position
(),
m_lexer
.
get_token_string
(),
parse_error
::
create
(
101
,
m_lexer
.
get_position
(),
exception_message
(
token_type
::
end_object
)));
}
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
single_include/nlohmann/json.hpp
View file @
850671b9
...
@@ -3955,10 +3955,9 @@ class parser
...
@@ -3955,10 +3955,9 @@ class parser
private:
private:
bool sax_parse_internal(json_sax_t* sax)
bool sax_parse_internal(json_sax_t* sax)
{
{
// two values for the structured values
enum class parse_state_t { array_value, object_value };
// stack to remember the hieararchy of structured values we are parsing
// stack to remember the hieararchy of structured values we are parsing
std::vector<parse_state_t> states;
// true = array; false = object
std::vector<bool> states;
// value to avoid a goto (see comment where set to true)
// value to avoid a goto (see comment where set to true)
bool skip_to_state_evaluation = false;
bool skip_to_state_evaluation = false;
...
@@ -4014,7 +4013,7 @@ class parser
...
@@ -4014,7 +4013,7 @@ class parser
}
}
// remember we are now inside an object
// remember we are now inside an object
states.push_back(
parse_state_t::object_valu
e);
states.push_back(
fals
e);
// parse values
// parse values
get_token();
get_token();
...
@@ -4042,7 +4041,7 @@ class parser
...
@@ -4042,7 +4041,7 @@ class parser
}
}
// remember we are now inside an array
// remember we are now inside an array
states.push_back(
parse_state_t::array_val
ue);
states.push_back(
tr
ue);
// parse values (no need to call get_token)
// parse values (no need to call get_token)
continue;
continue;
...
@@ -4152,104 +4151,98 @@ class parser
...
@@ -4152,104 +4151,98 @@ class parser
else
else
{
{
get_token();
get_token();
switch (states.back())
if (states.back()) // array
{
{
case parse_state_t::array_value:
// comma -> next value
if (last_token == token_type::value_separator)
{
{
// comma -> next value
// parse a new value
if (last_token == token_type::value_separator)
get_token();
continue;
}
// closing ]
if (JSON_LIKELY(last_token == token_type::end_array))
{
if (JSON_UNLIKELY(not sax->end_array()))
{
{
// parse a new value
return false;
get_token();
continue;
}
}
// closing ]
// We are done with this array. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_array))
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
}
}
else // object
{
// comma -> next value
if (last_token == token_type::value_separator)
{
get_token();
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{
{
if (JSON_UNLIKELY(not sax->end_array()))
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
{
return false;
return false;
}
}
// We are done with this array. Before we can parse
// a new value, we need to evaluate the new state
// first. By setting skip_to_state_evaluation to
// false, we are effectively jumping to the
// beginning of this switch.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
}
else
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{
{
return sax->parse_error(m_lexer.get_position(),
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::
end_array
)));
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::
name_separator
)));
}
}
// parse values
get_token();
continue;
}
}
case parse_state_t::object_value:
// closing }
if (JSON_LIKELY(last_token == token_type::end_object))
{
{
// comma -> next value
if (JSON_UNLIKELY(not sax->end_object()))
if (last_token == token_type::value_separator)
{
{
get_token();
return false;
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
}
// parse values
get_token();
continue;
}
}
// closing }
// We are done with this object. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_object))
// new value, we need to evaluate the new state first.
{
// By setting skip_to_state_evaluation to false, we
if (JSON_UNLIKELY(not sax->end_object()))
// are effectively jumping to the beginning of this if.
{
assert(not states.empty());
return false;
states.pop_back();
}
skip_to_state_evaluation = true;
continue;
// We are done with this object. Before we can
}
// parse a new value, we need to evaluate the new
else
// state first. By setting skip_to_state_evaluation
{
// to false, we are effectively jumping to the
return sax->parse_error(m_lexer.get_position(),
// beginning of this switch.
m_lexer.get_token_string(),
assert(not states.empty());
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
}
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
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