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
0835eb29
Commit
0835eb29
authored
Apr 17, 2016
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improved RFC compliance and code coverage
parent
f883a04c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
112 additions
and
8 deletions
+112
-8
src/json.hpp
src/json.hpp
+44
-4
src/json.hpp.re2c
src/json.hpp.re2c
+44
-4
test/unit.cpp
test/unit.cpp
+24
-0
No files found.
src/json.hpp
View file @
0835eb29
...
@@ -8993,6 +8993,8 @@ basic_json_parser_63:
...
@@ -8993,6 +8993,8 @@ basic_json_parser_63:
@complexity Linear in the length of the JSON pointer.
@complexity Linear in the length of the JSON pointer.
@throw std::out_of_range if the JSON pointer can not be resolved
@throw std::out_of_range if the JSON pointer can not be resolved
@throw std::domain_error if an array index begins with '0'
@throw std::invalid_argument if an array index was not a number
*/
*/
reference
get_unchecked
(
pointer
ptr
)
const
reference
get_unchecked
(
pointer
ptr
)
const
{
{
...
@@ -9002,18 +9004,27 @@ basic_json_parser_63:
...
@@ -9002,18 +9004,27 @@ basic_json_parser_63:
{
{
case
value_t
:
:
object
:
case
value_t
:
:
object
:
{
{
// use unchecked object access
ptr
=
&
ptr
->
operator
[](
reference_token
);
ptr
=
&
ptr
->
operator
[](
reference_token
);
break
;
break
;
}
}
case
value_t
:
:
array
:
case
value_t
:
:
array
:
{
{
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
if
(
reference_token
==
"-"
)
if
(
reference_token
==
"-"
)
{
{
// explicityly treat "-" as index beyond the end
ptr
=
&
ptr
->
operator
[](
ptr
->
m_value
.
array
->
size
());
ptr
=
&
ptr
->
operator
[](
ptr
->
m_value
.
array
->
size
());
}
}
else
else
{
{
// convert array index to number; unchecked access
ptr
=
&
ptr
->
operator
[](
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
ptr
=
&
ptr
->
operator
[](
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
}
}
break
;
break
;
...
@@ -9037,6 +9048,7 @@ basic_json_parser_63:
...
@@ -9037,6 +9048,7 @@ basic_json_parser_63:
{
{
case
value_t
:
:
object
:
case
value_t
:
:
object
:
{
{
// note: at performs range check
ptr
=
&
ptr
->
at
(
reference_token
);
ptr
=
&
ptr
->
at
(
reference_token
);
break
;
break
;
}
}
...
@@ -9045,12 +9057,20 @@ basic_json_parser_63:
...
@@ -9045,12 +9057,20 @@ basic_json_parser_63:
{
{
if
(
reference_token
==
"-"
)
if
(
reference_token
==
"-"
)
{
{
throw
std
::
out_of_range
(
"cannot resolve reference token '-'"
);
// "-" always fails the range check
throw
std
::
out_of_range
(
"array index '-' ("
+
std
::
to_string
(
ptr
->
m_value
.
array
->
size
())
+
") is out of range"
);
}
}
else
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
{
ptr
=
&
ptr
->
at
(
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
))
);
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
}
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
break
;
break
;
}
}
...
@@ -9080,6 +9100,7 @@ basic_json_parser_63:
...
@@ -9080,6 +9100,7 @@ basic_json_parser_63:
{
{
case
value_t
:
:
object
:
case
value_t
:
:
object
:
{
{
// use unchecked object access
ptr
=
&
ptr
->
operator
[](
reference_token
);
ptr
=
&
ptr
->
operator
[](
reference_token
);
break
;
break
;
}
}
...
@@ -9088,10 +9109,19 @@ basic_json_parser_63:
...
@@ -9088,10 +9109,19 @@ basic_json_parser_63:
{
{
if
(
reference_token
==
"-"
)
if
(
reference_token
==
"-"
)
{
{
// "-" cannot be used for const access
throw
std
::
out_of_range
(
"array index '-' ("
+
throw
std
::
out_of_range
(
"array index '-' ("
+
std
::
to_string
(
ptr
->
m_value
.
array
->
size
())
+
std
::
to_string
(
ptr
->
m_value
.
array
->
size
())
+
") is out of range"
);
") is out of range"
);
}
}
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
// use unchecked array access
ptr
=
&
ptr
->
operator
[](
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
ptr
=
&
ptr
->
operator
[](
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
break
;
break
;
}
}
...
@@ -9114,6 +9144,7 @@ basic_json_parser_63:
...
@@ -9114,6 +9144,7 @@ basic_json_parser_63:
{
{
case
value_t
:
:
object
:
case
value_t
:
:
object
:
{
{
// note: at performs range check
ptr
=
&
ptr
->
at
(
reference_token
);
ptr
=
&
ptr
->
at
(
reference_token
);
break
;
break
;
}
}
...
@@ -9122,10 +9153,19 @@ basic_json_parser_63:
...
@@ -9122,10 +9153,19 @@ basic_json_parser_63:
{
{
if
(
reference_token
==
"-"
)
if
(
reference_token
==
"-"
)
{
{
// "-" always fails the range check
throw
std
::
out_of_range
(
"array index '-' ("
+
throw
std
::
out_of_range
(
"array index '-' ("
+
std
::
to_string
(
ptr
->
m_value
.
array
->
size
())
+
std
::
to_string
(
ptr
->
m_value
.
array
->
size
())
+
") is out of range"
);
") is out of range"
);
}
}
// error condition (cf. RFC 6901, Sect. 4)
if
(
reference_token
.
size
()
>
1
and
reference_token
[
0
]
==
'0'
)
{
throw
std
::
domain_error
(
"array index must not begin with '0'"
);
}
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
ptr
=
&
ptr
->
at
(
static_cast
<
size_t
>
(
std
::
stoi
(
reference_token
)));
break
;
break
;
}
}
...
...
src/json.hpp.re2c
View file @
0835eb29
...
@@ -8303,6 +8303,8 @@ class basic_json
...
@@ -8303,6 +8303,8 @@ class basic_json
@complexity Linear in the length of the JSON pointer.
@complexity Linear in the length of the JSON pointer.
@throw std::out_of_range if the JSON pointer can not be resolved
@throw std::out_of_range if the JSON pointer can not be resolved
@throw std::domain_error if an array index begins with '0'
@throw std::invalid_argument if an array index was not a number
*/
*/
reference get_unchecked(pointer ptr) const
reference get_unchecked(pointer ptr) const
{
{
...
@@ -8312,18 +8314,27 @@ class basic_json
...
@@ -8312,18 +8314,27 @@ class basic_json
{
{
case value_t::object:
case value_t::object:
{
{
// use unchecked object access
ptr = &ptr->operator[](reference_token);
ptr = &ptr->operator[](reference_token);
break;
break;
}
}
case value_t::array:
case value_t::array:
{
{
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
throw std::domain_error("array index must not begin with '0'");
}
if (reference_token == "-")
if (reference_token == "-")
{
{
// explicityly treat "-" as index beyond the end
ptr = &ptr->operator[](ptr->m_value.array->size());
ptr = &ptr->operator[](ptr->m_value.array->size());
}
}
else
else
{
{
// convert array index to number; unchecked access
ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
}
}
break;
break;
...
@@ -8347,6 +8358,7 @@ class basic_json
...
@@ -8347,6 +8358,7 @@ class basic_json
{
{
case value_t::object:
case value_t::object:
{
{
// note: at performs range check
ptr = &ptr->at(reference_token);
ptr = &ptr->at(reference_token);
break;
break;
}
}
...
@@ -8355,12 +8367,20 @@ class basic_json
...
@@ -8355,12 +8367,20 @@ class basic_json
{
{
if (reference_token == "-")
if (reference_token == "-")
{
{
throw std::out_of_range("cannot resolve reference token '-'");
// "-" always fails the range check
throw std::out_of_range("array index '-' (" +
std::to_string(ptr->m_value.array->size()) +
") is out of range");
}
}
else
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
{
ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token))
);
throw std::domain_error("array index must not begin with '0'"
);
}
}
// note: at performs range check
ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
break;
break;
}
}
...
@@ -8390,6 +8410,7 @@ class basic_json
...
@@ -8390,6 +8410,7 @@ class basic_json
{
{
case value_t::object:
case value_t::object:
{
{
// use unchecked object access
ptr = &ptr->operator[](reference_token);
ptr = &ptr->operator[](reference_token);
break;
break;
}
}
...
@@ -8398,10 +8419,19 @@ class basic_json
...
@@ -8398,10 +8419,19 @@ class basic_json
{
{
if (reference_token == "-")
if (reference_token == "-")
{
{
// "-" cannot be used for const access
throw std::out_of_range("array index '-' (" +
throw std::out_of_range("array index '-' (" +
std::to_string(ptr->m_value.array->size()) +
std::to_string(ptr->m_value.array->size()) +
") is out of range");
") is out of range");
}
}
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
throw std::domain_error("array index must not begin with '0'");
}
// use unchecked array access
ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
break;
break;
}
}
...
@@ -8424,6 +8454,7 @@ class basic_json
...
@@ -8424,6 +8454,7 @@ class basic_json
{
{
case value_t::object:
case value_t::object:
{
{
// note: at performs range check
ptr = &ptr->at(reference_token);
ptr = &ptr->at(reference_token);
break;
break;
}
}
...
@@ -8432,10 +8463,19 @@ class basic_json
...
@@ -8432,10 +8463,19 @@ class basic_json
{
{
if (reference_token == "-")
if (reference_token == "-")
{
{
// "-" always fails the range check
throw std::out_of_range("array index '-' (" +
throw std::out_of_range("array index '-' (" +
std::to_string(ptr->m_value.array->size()) +
std::to_string(ptr->m_value.array->size()) +
") is out of range");
") is out of range");
}
}
// error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0')
{
throw std::domain_error("array index must not begin with '0'");
}
// note: at performs range check
ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
break;
break;
}
}
...
...
test/unit.cpp
View file @
0835eb29
...
@@ -12196,6 +12196,7 @@ TEST_CASE("JSON pointers")
...
@@ -12196,6 +12196,7 @@ TEST_CASE("JSON pointers")
SECTION
(
"nonconst access"
)
SECTION
(
"nonconst access"
)
{
{
json
j
=
{
1
,
2
,
3
};
json
j
=
{
1
,
2
,
3
};
const
json
j_const
=
j
;
// check reading access
// check reading access
CHECK
(
j
[
"/0"
_json_pointer
]
==
j
[
0
]);
CHECK
(
j
[
"/0"
_json_pointer
]
==
j
[
0
]);
...
@@ -12214,9 +12215,32 @@ TEST_CASE("JSON pointers")
...
@@ -12214,9 +12215,32 @@ TEST_CASE("JSON pointers")
j
[
"/5"
_json_pointer
]
=
55
;
j
[
"/5"
_json_pointer
]
=
55
;
CHECK
(
j
==
json
({
1
,
13
,
3
,
33
,
nullptr
,
55
}));
CHECK
(
j
==
json
({
1
,
13
,
3
,
33
,
nullptr
,
55
}));
// error with leading 0
CHECK_THROWS_AS
(
j
[
"/01"
_json_pointer
],
std
::
domain_error
);
CHECK_THROWS_WITH
(
j
[
"/01"
_json_pointer
],
"array index must not begin with '0'"
);
CHECK_THROWS_AS
(
j_const
[
"/01"
_json_pointer
],
std
::
domain_error
);
CHECK_THROWS_WITH
(
j_const
[
"/01"
_json_pointer
],
"array index must not begin with '0'"
);
CHECK_THROWS_AS
(
j
.
at
(
"/01"
_json_pointer
),
std
::
domain_error
);
CHECK_THROWS_WITH
(
j
.
at
(
"/01"
_json_pointer
),
"array index must not begin with '0'"
);
CHECK_THROWS_AS
(
j_const
.
at
(
"/01"
_json_pointer
),
std
::
domain_error
);
CHECK_THROWS_WITH
(
j_const
.
at
(
"/01"
_json_pointer
),
"array index must not begin with '0'"
);
// error with incorrect numbers
CHECK_THROWS_AS
(
j
[
"/one"
_json_pointer
]
=
1
,
std
::
invalid_argument
);
// assign to "-"
// assign to "-"
j
[
"/-"
_json_pointer
]
=
99
;
j
[
"/-"
_json_pointer
]
=
99
;
CHECK
(
j
==
json
({
1
,
13
,
3
,
33
,
nullptr
,
55
,
99
}));
CHECK
(
j
==
json
({
1
,
13
,
3
,
33
,
nullptr
,
55
,
99
}));
// error when using "-" in const object
CHECK_THROWS_AS
(
j_const
[
"/-"
_json_pointer
],
std
::
out_of_range
);
CHECK_THROWS_WITH
(
j_const
[
"/-"
_json_pointer
],
"array index '-' (3) is out of range"
);
// error when using "-" with at
CHECK_THROWS_AS
(
j
.
at
(
"/-"
_json_pointer
),
std
::
out_of_range
);
CHECK_THROWS_WITH
(
j
.
at
(
"/-"
_json_pointer
),
"array index '-' (7) is out of range"
);
CHECK_THROWS_AS
(
j_const
.
at
(
"/-"
_json_pointer
),
std
::
out_of_range
);
CHECK_THROWS_WITH
(
j_const
.
at
(
"/-"
_json_pointer
),
"array index '-' (3) is out of range"
);
}
}
SECTION
(
"const access"
)
SECTION
(
"const access"
)
...
...
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