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
eef80590
Commit
eef80590
authored
Aug 20, 2016
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allowing parsing from contiguous containers
parent
6f3554f0
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
148 additions
and
56 deletions
+148
-56
src/json.hpp
src/json.hpp
+38
-13
src/json.hpp.re2c
src/json.hpp.re2c
+38
-13
test/src/unit-deserialization.cpp
test/src/unit-deserialization.cpp
+72
-30
No files found.
src/json.hpp
View file @
eef80590
...
@@ -5956,11 +5956,13 @@ class basic_json
...
@@ -5956,11 +5956,13 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
/*
static basic_json parse(const string_t& s,
static basic_json parse(const string_t& s,
const parser_callback_t cb = nullptr)
const parser_callback_t cb = nullptr)
{
{
return parser(s, cb).parse();
return parser(s, cb).parse();
}
}
*/
/*!
/*!
@brief deserialize from string literal
@brief deserialize from string literal
...
@@ -6012,10 +6014,10 @@ class basic_json
...
@@ -6012,10 +6014,10 @@ class basic_json
}
}
/*!
/*!
@brief deserialize from a
container
with contiguous storage
@brief deserialize from a
iterator range
with contiguous storage
This function reads from a
nonempty iterator range of a container with
This function reads from a
n iterator range of a container with contiguous
contiguous
storage of 1-byte values. Compatible container types include
storage of 1-byte values. Compatible container types include
`std::vector`, `std::string`, `std::array`, `std::valarray`, and
`std::vector`, `std::string`, `std::array`, `std::valarray`, and
`std::initializer_list`. Furthermore, C-style arrays can be used with
`std::initializer_list`. Furthermore, C-style arrays can be used with
`std::begin()`/`std::end()`. User-defined containers can be used as long
`std::begin()`/`std::end()`. User-defined containers can be used as long
...
@@ -6025,9 +6027,7 @@ class basic_json
...
@@ -6025,9 +6027,7 @@ class basic_json
undefined behavior. **This precondition is enforced with an assertion.**
undefined behavior. **This precondition is enforced with an assertion.**
@pre Each element in the range has a size of 1 byte. Violating this
@pre Each element in the range has a size of 1 byte. Violating this
precondition yields undefined behavior. **This precondition is enforced
precondition yields undefined behavior. **This precondition is enforced
with an assertion.**
with a static assertion.**
@pre The iterator range is nonempty. Violating this precondition yields
undefined behavior. **This precondition is enforced with an assertion.**
@warning There is no way to enforce the preconditions at compile-time. If
@warning There is no way to enforce the preconditions at compile-time. If
the function is called with noncompliant iterators, the behavior
the function is called with noncompliant iterators, the behavior
...
@@ -6053,7 +6053,9 @@ class basic_json
...
@@ -6053,7 +6053,9 @@ class basic_json
*/
*/
template
<
class
IteratorType
,
typename
template
<
class
IteratorType
,
typename
std
::
enable_if
<
std
::
enable_if
<
std
::
is_same
<
typename
std
::
iterator_traits
<
IteratorType
>
::
iterator_category
,
std
::
random_access_iterator_tag
>::
value
std
::
is_base_of
<
std
::
random_access_iterator_tag
,
typename
std
::
iterator_traits
<
IteratorType
>
::
iterator_category
>::
value
,
int
>::
type
,
int
>::
type
=
0
>
=
0
>
static
basic_json
parse
(
IteratorType
first
,
IteratorType
last
,
static
basic_json
parse
(
IteratorType
first
,
IteratorType
last
,
...
@@ -6069,17 +6071,40 @@ class basic_json
...
@@ -6069,17 +6071,40 @@ class basic_json
}).
first
);
}).
first
);
// assertion to check that each element is 1 byte long
// assertion to check that each element is 1 byte long
assert
(
std
::
all_of
(
first
,
last
,
[](
decltype
(
*
first
)
val
)
static_assert
(
sizeof
(
typename
std
::
iterator_traits
<
IteratorType
>::
value_type
)
==
1
,
{
"each element in the iterator range must have the size of 1 byte"
);
return
sizeof
(
val
)
==
1
;
}));
// assertion that the iterator range is not empty
// if iterator range is empty, create a parser with an empty string
assert
(
std
::
distance
(
first
,
last
)
>
0
);
// to generate "unexpected EOF" error message
if
(
std
::
distance
(
first
,
last
)
<=
0
)
{
return
parser
(
""
).
parse
();
}
return
parser
(
first
,
last
,
cb
).
parse
();
return
parser
(
first
,
last
,
cb
).
parse
();
}
}
template
<
class
ContiguousContainer
,
typename
std
::
enable_if
<
std
::
is_base_of
<
std
::
random_access_iterator_tag
,
typename
std
::
iterator_traits
<
decltype
(
std
::
begin
(
std
::
declval
<
ContiguousContainer
>()))
>::
iterator_category
>::
value
,
int
>::
type
=
0
>
static
basic_json
parse
(
const
ContiguousContainer
&
c
,
const
parser_callback_t
cb
=
nullptr
)
{
// delegate the call to the iterator-range parse overload
return
parse
(
std
::
begin
(
c
),
std
::
end
(
c
),
cb
);
}
template
<
class
T
,
std
::
size_t
N
>
static
basic_json
parse
(
T
(
&
array
)[
N
],
const
parser_callback_t
cb
=
nullptr
)
{
// delegate the call to the iterator-range parse overload
return
parse
(
std
::
begin
(
array
),
std
::
end
(
array
),
cb
);
}
/*!
/*!
@brief deserialize from stream
@brief deserialize from stream
...
...
src/json.hpp.re2c
View file @
eef80590
...
@@ -5956,11 +5956,13 @@ class basic_json
...
@@ -5956,11 +5956,13 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
/*
static basic_json parse(const string_t& s,
static basic_json parse(const string_t& s,
const parser_callback_t cb = nullptr)
const parser_callback_t cb = nullptr)
{
{
return parser(s, cb).parse();
return parser(s, cb).parse();
}
}
*/
/*!
/*!
@brief deserialize from string literal
@brief deserialize from string literal
...
@@ -6012,10 +6014,10 @@ class basic_json
...
@@ -6012,10 +6014,10 @@ class basic_json
}
}
/*!
/*!
@brief deserialize from a
container
with contiguous storage
@brief deserialize from a
iterator range
with contiguous storage
This function reads from a
nonempty iterator range of a container with
This function reads from a
n iterator range of a container with contiguous
contiguous
storage of 1-byte values. Compatible container types include
storage of 1-byte values. Compatible container types include
`std::vector`, `std::string`, `std::array`, `std::valarray`, and
`std::vector`, `std::string`, `std::array`, `std::valarray`, and
`std::initializer_list`. Furthermore, C-style arrays can be used with
`std::initializer_list`. Furthermore, C-style arrays can be used with
`std::begin()`/`std::end()`. User-defined containers can be used as long
`std::begin()`/`std::end()`. User-defined containers can be used as long
...
@@ -6025,9 +6027,7 @@ class basic_json
...
@@ -6025,9 +6027,7 @@ class basic_json
undefined behavior. **This precondition is enforced with an assertion.**
undefined behavior. **This precondition is enforced with an assertion.**
@pre Each element in the range has a size of 1 byte. Violating this
@pre Each element in the range has a size of 1 byte. Violating this
precondition yields undefined behavior. **This precondition is enforced
precondition yields undefined behavior. **This precondition is enforced
with an assertion.**
with a static assertion.**
@pre The iterator range is nonempty. Violating this precondition yields
undefined behavior. **This precondition is enforced with an assertion.**
@warning There is no way to enforce the preconditions at compile-time. If
@warning There is no way to enforce the preconditions at compile-time. If
the function is called with noncompliant iterators, the behavior
the function is called with noncompliant iterators, the behavior
...
@@ -6053,7 +6053,9 @@ class basic_json
...
@@ -6053,7 +6053,9 @@ class basic_json
*/
*/
template <class IteratorType, typename
template <class IteratorType, typename
std::enable_if<
std::enable_if<
std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<IteratorType>::iterator_category>::value
, int>::type
, int>::type
= 0>
= 0>
static basic_json parse(IteratorType first, IteratorType last,
static basic_json parse(IteratorType first, IteratorType last,
...
@@ -6069,17 +6071,40 @@ class basic_json
...
@@ -6069,17 +6071,40 @@ class basic_json
}).first);
}).first);
// assertion to check that each element is 1 byte long
// assertion to check that each element is 1 byte long
assert(std::all_of(first, last, [](decltype(*first) val)
static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
{
"each element in the iterator range must have the size of 1 byte");
return sizeof(val) == 1;
}));
// assertion that the iterator range is not empty
// if iterator range is empty, create a parser with an empty string
assert(std::distance(first, last) > 0);
// to generate "unexpected EOF" error message
if (std::distance(first, last) <= 0)
{
return parser("").parse();
}
return parser(first, last, cb).parse();
return parser(first, last, cb).parse();
}
}
template<class ContiguousContainer, typename
std::enable_if<
std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer>()))>::iterator_category>::value
, int>::type = 0>
static basic_json parse(const ContiguousContainer& c,
const parser_callback_t cb = nullptr)
{
// delegate the call to the iterator-range parse overload
return parse(std::begin(c), std::end(c), cb);
}
template<class T, std::size_t N>
static basic_json parse(T (&array)[N],
const parser_callback_t cb = nullptr)
{
// delegate the call to the iterator-range parse overload
return parse(std::begin(array), std::end(array), cb);
}
/*!
/*!
@brief deserialize from stream
@brief deserialize from stream
...
...
test/src/unit-deserialization.cpp
View file @
eef80590
...
@@ -82,40 +82,82 @@ TEST_CASE("deserialization")
...
@@ -82,40 +82,82 @@ TEST_CASE("deserialization")
SECTION
(
"contiguous containers"
)
SECTION
(
"contiguous containers"
)
{
{
SECTION
(
"
from std::vector
"
)
SECTION
(
"
directly
"
)
{
{
std
::
vector
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
SECTION
(
"from std::vector"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
std
::
vector
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
v
)
==
json
(
true
));
}
SECTION
(
"from std::array"
)
{
std
::
array
<
uint8_t
,
5
>
v
{
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
}
};
CHECK
(
json
::
parse
(
v
)
==
json
(
true
));
}
SECTION
(
"from array"
)
{
uint8_t
v
[]
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
v
)
==
json
(
true
));
}
SECTION
(
"from std::string"
)
{
std
::
string
v
=
{
't'
,
'r'
,
'u'
,
'e'
};
CHECK
(
json
::
parse
(
v
)
==
json
(
true
));
}
SECTION
(
"from std::initializer_list"
)
{
std
::
initializer_list
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
v
)
==
json
(
true
));
}
}
}
SECTION
(
"
from std::array
"
)
SECTION
(
"
via iterator range
"
)
{
{
std
::
array
<
uint8_t
,
5
>
v
{
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
}
};
SECTION
(
"from std::vector"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
}
std
::
vector
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
SECTION
(
"from array"
)
}
{
uint8_t
v
[]
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
SECTION
(
"from std::array"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
}
std
::
array
<
uint8_t
,
5
>
v
{
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
}
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
SECTION
(
"from std::string"
)
}
{
std
::
string
v
=
{
't'
,
'r'
,
'u'
,
'e'
};
SECTION
(
"from array"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
}
uint8_t
v
[]
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
SECTION
(
"from std::initializer_list"
)
}
{
std
::
initializer_list
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
SECTION
(
"from std::string"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
}
std
::
string
v
=
{
't'
,
'r'
,
'u'
,
'e'
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
SECTION
(
"from std::valarray"
)
}
{
std
::
valarray
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
SECTION
(
"from std::initializer_list"
)
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
{
std
::
initializer_list
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
}
SECTION
(
"from std::valarray"
)
{
std
::
valarray
<
uint8_t
>
v
=
{
't'
,
'r'
,
'u'
,
'e'
,
'\0'
};
CHECK
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
))
==
json
(
true
));
}
SECTION
(
"with empty range"
)
{
std
::
vector
<
uint8_t
>
v
;
CHECK_THROWS_AS
(
json
::
parse
(
std
::
begin
(
v
),
std
::
end
(
v
)),
std
::
invalid_argument
);
}
}
}
}
}
}
}
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