added a parser for continguous containers

This commit is contained in:
Niels 2016-08-14 14:18:25 +02:00
parent 03de590372
commit b76f5506d7
3 changed files with 169 additions and 67 deletions

View file

@ -3960,7 +3960,7 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
pos refers to the last element, the `end()` iterator is returned.
@tparam InteratorType an @ref iterator or @ref const_iterator
@tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@ -3982,7 +3982,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType}
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@ -3991,13 +3991,13 @@ class basic_json
@since version 1.0.0
*/
template <class InteratorType, typename
template <class IteratorType, typename
std::enable_if<
std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
std::is_same<IteratorType, typename basic_json_t::iterator>::value or
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType pos)
IteratorType erase(IteratorType pos)
{
// make sure iterator fits the current value
if (this != pos.m_object)
@ -4005,7 +4005,7 @@ class basic_json
throw std::domain_error("iterator does not fit current value");
}
InteratorType result = end();
IteratorType result = end();
switch (m_type)
{
@ -4069,7 +4069,7 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
second refers to the last element, the `end()` iterator is returned.
@tparam InteratorType an @ref iterator or @ref const_iterator
@tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@ -4092,7 +4092,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType_IteratorType}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@sa @ref erase(const size_type) -- removes the element from an array at
@ -4100,13 +4100,13 @@ class basic_json
@since version 1.0.0
*/
template <class InteratorType, typename
template <class IteratorType, typename
std::enable_if<
std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
std::is_same<IteratorType, typename basic_json_t::iterator>::value or
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType first, InteratorType last)
IteratorType erase(IteratorType first, IteratorType last)
{
// make sure iterator fits the current value
if (this != first.m_object or this != last.m_object)
@ -4114,7 +4114,7 @@ class basic_json
throw std::domain_error("iterators do not fit current value");
}
InteratorType result = end();
IteratorType result = end();
switch (m_type)
{
@ -4186,8 +4186,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__key_type}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const size_type) -- removes the element from an array at
the given index
@ -4223,8 +4223,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__size_type}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@ -7504,21 +7504,29 @@ class basic_json
/// the char type to use in the lexer
using lexer_char_t = unsigned char;
/// constructor with a given buffer
explicit lexer(const string_t& s) noexcept
: m_stream(nullptr), m_buffer(s)
/// a lexer from a buffer with given length
lexer(const lexer_char_t* buff, const size_t len) noexcept
: m_stream(nullptr), m_buffer(), m_content(buff)
{
m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
assert(m_content != nullptr);
m_start = m_cursor = m_content;
m_limit = m_content + s.size();
m_limit = m_content + len;
}
/// constructor with a given stream
explicit lexer(std::istream* s) noexcept
: m_stream(s), m_buffer()
/// a lexer from a string literal
explicit lexer(const typename string_t::value_type* buff) noexcept
: m_stream(nullptr), m_buffer(),
m_content(reinterpret_cast<const lexer_char_t*>(buff))
{
assert(m_content != nullptr);
m_start = m_cursor = m_content;
m_limit = m_content + strlen(buff);
}
/// a lexer from an input stream
explicit lexer(std::istream& s)
: m_stream(&s), m_buffer()
{
assert(m_stream != nullptr);
std::getline(*m_stream, m_buffer);
m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
assert(m_content != nullptr);
@ -8853,17 +8861,41 @@ basic_json_parser_63:
class parser
{
public:
/// constructor for strings
/// a parser reading from a string literal
parser(const typename string_t::value_type* buff, parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(buff)
{
// read first token
get_token();
}
/// a parser reading from a string container
parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(s)
: callback(cb),
m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(s.c_str()), s.size())
{
// read first token
get_token();
}
/// a parser reading from an input stream
parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(&_is)
parser(std::istream& is, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(is)
{
// read first token
get_token();
}
/// a parser reading from a container with continguous storage
template <class IteratorType, typename
std::enable_if<
std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
, int>::type
= 0>
parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) noexcept
: callback(cb),
m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
static_cast<size_t>(std::distance(first, last)))
{
// read first token
get_token();

View file

@ -3960,7 +3960,7 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
pos refers to the last element, the `end()` iterator is returned.
@tparam InteratorType an @ref iterator or @ref const_iterator
@tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@ -3982,7 +3982,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType}
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@ -3991,13 +3991,13 @@ class basic_json
@since version 1.0.0
*/
template <class InteratorType, typename
template <class IteratorType, typename
std::enable_if<
std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
std::is_same<IteratorType, typename basic_json_t::iterator>::value or
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType pos)
IteratorType erase(IteratorType pos)
{
// make sure iterator fits the current value
if (this != pos.m_object)
@ -4005,7 +4005,7 @@ class basic_json
throw std::domain_error("iterator does not fit current value");
}
InteratorType result = end();
IteratorType result = end();
switch (m_type)
{
@ -4069,7 +4069,7 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
second refers to the last element, the `end()` iterator is returned.
@tparam InteratorType an @ref iterator or @ref const_iterator
@tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@ -4092,7 +4092,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType_IteratorType}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@sa @ref erase(const size_type) -- removes the element from an array at
@ -4100,13 +4100,13 @@ class basic_json
@since version 1.0.0
*/
template <class InteratorType, typename
template <class IteratorType, typename
std::enable_if<
std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
std::is_same<IteratorType, typename basic_json_t::iterator>::value or
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType first, InteratorType last)
IteratorType erase(IteratorType first, IteratorType last)
{
// make sure iterator fits the current value
if (this != first.m_object or this != last.m_object)
@ -4114,7 +4114,7 @@ class basic_json
throw std::domain_error("iterators do not fit current value");
}
InteratorType result = end();
IteratorType result = end();
switch (m_type)
{
@ -4186,8 +4186,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__key_type}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const size_type) -- removes the element from an array at
the given index
@ -4223,8 +4223,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__size_type}
@sa @ref erase(InteratorType) -- removes the element at a given position
@sa @ref erase(InteratorType, InteratorType) -- removes the elements in
@sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@ -7504,21 +7504,29 @@ class basic_json
/// the char type to use in the lexer
using lexer_char_t = unsigned char;
/// constructor with a given buffer
explicit lexer(const string_t& s) noexcept
: m_stream(nullptr), m_buffer(s)
/// a lexer from a buffer with given length
lexer(const lexer_char_t* buff, const size_t len) noexcept
: m_stream(nullptr), m_buffer(), m_content(buff)
{
m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
assert(m_content != nullptr);
m_start = m_cursor = m_content;
m_limit = m_content + s.size();
m_limit = m_content + len;
}
/// constructor with a given stream
explicit lexer(std::istream* s) noexcept
: m_stream(s), m_buffer()
/// a lexer from a string literal
explicit lexer(const typename string_t::value_type* buff) noexcept
: m_stream(nullptr), m_buffer(),
m_content(reinterpret_cast<const lexer_char_t*>(buff))
{
assert(m_content != nullptr);
m_start = m_cursor = m_content;
m_limit = m_content + strlen(buff);
}
/// a lexer from an input stream
explicit lexer(std::istream& s)
: m_stream(&s), m_buffer()
{
assert(m_stream != nullptr);
std::getline(*m_stream, m_buffer);
m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
assert(m_content != nullptr);
@ -8150,17 +8158,41 @@ class basic_json
class parser
{
public:
/// constructor for strings
/// a parser reading from a string literal
parser(const typename string_t::value_type* buff, parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(buff)
{
// read first token
get_token();
}
/// a parser reading from a string container
parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(s)
: callback(cb),
m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(s.c_str()), s.size())
{
// read first token
get_token();
}
/// a parser reading from an input stream
parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(&_is)
parser(std::istream& is, const parser_callback_t cb = nullptr) noexcept
: callback(cb), m_lexer(is)
{
// read first token
get_token();
}
/// a parser reading from a container with continguous storage
template <class IteratorType, typename
std::enable_if<
std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
, int>::type
= 0>
parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) noexcept
: callback(cb),
m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
static_cast<size_t>(std::distance(first, last)))
{
// read first token
get_token();

View file

@ -32,6 +32,8 @@ SOFTWARE.
#include "json.hpp"
using nlohmann::json;
#include <valarray>
TEST_CASE("parser class")
{
SECTION("parse")
@ -743,11 +745,47 @@ TEST_CASE("parser class")
}
}
SECTION("copy constructor")
SECTION("constructing from continguous containers")
{
json::string_t* s = new json::string_t("[1,2,3,4]");
json::parser p(*s);
delete s;
CHECK(p.parse() == json({1, 2, 3, 4}));
SECTION("from std::vector")
{
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
SECTION("from std::array")
{
std::array<uint8_t, 4> v { {'t', 'r', 'u', 'e'} };
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
SECTION("from array")
{
uint8_t v[] = {'t', 'r', 'u', 'e'};
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
SECTION("from char literal")
{
CHECK (json::parser("true").parse() == json(true));
}
SECTION("from std::string")
{
std::string v = {'t', 'r', 'u', 'e'};
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
SECTION("from std::initializer_list")
{
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e', '\0'};
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
SECTION("from std::valarray")
{
std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK (json::parser(std::begin(v), std::end(v)).parse() == json(true));
}
}
}