Merge branch 'develop' into feature/iterator_range_parsing
This commit is contained in:
commit
cda84ba323
4 changed files with 199 additions and 16 deletions
22
src/json.hpp
22
src/json.hpp
|
@ -7890,7 +7890,7 @@ class basic_json
|
||||||
};
|
};
|
||||||
if ((m_limit - m_cursor) < 5)
|
if ((m_limit - m_cursor) < 5)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yybm[0 + yych] & 32)
|
if (yybm[0 + yych] & 32)
|
||||||
|
@ -8024,7 +8024,7 @@ basic_json_parser_6:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yybm[0 + yych] & 32)
|
if (yybm[0 + yych] & 32)
|
||||||
|
@ -8094,7 +8094,7 @@ basic_json_parser_15:
|
||||||
m_marker = ++m_cursor;
|
m_marker = ++m_cursor;
|
||||||
if ((m_limit - m_cursor) < 3)
|
if ((m_limit - m_cursor) < 3)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yybm[0 + yych] & 64)
|
if (yybm[0 + yych] & 64)
|
||||||
|
@ -8187,7 +8187,7 @@ basic_json_parser_31:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
basic_json_parser_32:
|
basic_json_parser_32:
|
||||||
|
@ -8224,7 +8224,7 @@ basic_json_parser_36:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= 'e')
|
if (yych <= 'e')
|
||||||
|
@ -8368,7 +8368,7 @@ basic_json_parser_43:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= '@')
|
if (yych <= '@')
|
||||||
|
@ -8404,7 +8404,7 @@ basic_json_parser_44:
|
||||||
m_marker = ++m_cursor;
|
m_marker = ++m_cursor;
|
||||||
if ((m_limit - m_cursor) < 3)
|
if ((m_limit - m_cursor) < 3)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= 'D')
|
if (yych <= 'D')
|
||||||
|
@ -8445,7 +8445,7 @@ basic_json_parser_47:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= '/')
|
if (yych <= '/')
|
||||||
|
@ -8487,7 +8487,7 @@ basic_json_parser_54:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= '@')
|
if (yych <= '@')
|
||||||
|
@ -8541,7 +8541,7 @@ basic_json_parser_60:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= '@')
|
if (yych <= '@')
|
||||||
|
@ -8582,7 +8582,7 @@ basic_json_parser_63:
|
||||||
++m_cursor;
|
++m_cursor;
|
||||||
if (m_limit <= m_cursor)
|
if (m_limit <= m_cursor)
|
||||||
{
|
{
|
||||||
fill_line_buffer(); // LCOV_EXCL_LINE;
|
fill_line_buffer();
|
||||||
}
|
}
|
||||||
yych = *m_cursor;
|
yych = *m_cursor;
|
||||||
if (yych <= '@')
|
if (yych <= '@')
|
||||||
|
|
|
@ -7854,7 +7854,7 @@ class basic_json
|
||||||
re2c:define:YYCURSOR = m_cursor;
|
re2c:define:YYCURSOR = m_cursor;
|
||||||
re2c:define:YYLIMIT = m_limit;
|
re2c:define:YYLIMIT = m_limit;
|
||||||
re2c:define:YYMARKER = m_marker;
|
re2c:define:YYMARKER = m_marker;
|
||||||
re2c:define:YYFILL = "fill_line_buffer(); // LCOV_EXCL_LINE";
|
re2c:define:YYFILL = "fill_line_buffer()";
|
||||||
re2c:yyfill:parameter = 0;
|
re2c:yyfill:parameter = 0;
|
||||||
re2c:indent:string = " ";
|
re2c:indent:string = " ";
|
||||||
re2c:indent:top = 1;
|
re2c:indent:top = 1;
|
||||||
|
|
|
@ -28,13 +28,14 @@ SOFTWARE.
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#define private public
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
// special test case to check if memory is leaked if constructor throws
|
// special test case to check if memory is leaked if constructor throws
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct my_allocator : std::allocator<T>
|
struct bad_allocator : std::allocator<T>
|
||||||
{
|
{
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
void construct(T*, Args&& ...)
|
void construct(T*, Args&& ...)
|
||||||
|
@ -48,16 +49,186 @@ TEST_CASE("bad_alloc")
|
||||||
SECTION("bad_alloc")
|
SECTION("bad_alloc")
|
||||||
{
|
{
|
||||||
// create JSON type using the throwing allocator
|
// create JSON type using the throwing allocator
|
||||||
using my_json = nlohmann::basic_json<std::map,
|
using bad_json = nlohmann::basic_json<std::map,
|
||||||
std::vector,
|
std::vector,
|
||||||
std::string,
|
std::string,
|
||||||
bool,
|
bool,
|
||||||
std::int64_t,
|
std::int64_t,
|
||||||
std::uint64_t,
|
std::uint64_t,
|
||||||
double,
|
double,
|
||||||
my_allocator>;
|
bad_allocator>;
|
||||||
|
|
||||||
// creating an object should throw
|
// creating an object should throw
|
||||||
CHECK_THROWS_AS(my_json j(my_json::value_t::object), std::bad_alloc);
|
CHECK_THROWS_AS(bad_json j(bad_json::value_t::object), std::bad_alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next_construct_fails = false;
|
||||||
|
bool next_destroy_fails = false;
|
||||||
|
bool next_deallocate_fails = false;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct my_allocator : std::allocator<T>
|
||||||
|
{
|
||||||
|
template<class... Args>
|
||||||
|
void construct(T* p, Args&& ... args)
|
||||||
|
{
|
||||||
|
if (next_construct_fails)
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::new(reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T* p, std::size_t n)
|
||||||
|
{
|
||||||
|
if (next_deallocate_fails)
|
||||||
|
{
|
||||||
|
next_deallocate_fails = false;
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::allocator<T>::deallocate(p, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy(T* p)
|
||||||
|
{
|
||||||
|
if (next_destroy_fails)
|
||||||
|
{
|
||||||
|
next_destroy_fails = false;
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("controlled bad_alloc")
|
||||||
|
{
|
||||||
|
// create JSON type using the throwing allocator
|
||||||
|
using my_json = nlohmann::basic_json<std::map,
|
||||||
|
std::vector,
|
||||||
|
std::string,
|
||||||
|
bool,
|
||||||
|
std::int64_t,
|
||||||
|
std::uint64_t,
|
||||||
|
double,
|
||||||
|
my_allocator>;
|
||||||
|
|
||||||
|
SECTION("class json_value")
|
||||||
|
{
|
||||||
|
SECTION("json_value(value_t)")
|
||||||
|
{
|
||||||
|
SECTION("object")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
auto t = my_json::value_t::object;
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(t));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
auto t = my_json::value_t::array;
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(t));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
SECTION("string")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
auto t = my_json::value_t::string;
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(t));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("json_value(const string_t&)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
my_json::string_t v("foo");
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(v));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SECTION("json_value(const object_t&)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
my_json::object_t v {{"foo", "bar"}};
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(v));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
SECTION("json_value(const array_t&)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
my_json::array_t v = {"foo", "bar", "baz"};
|
||||||
|
CHECK_NOTHROW(my_json::json_value j(v));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("class basic_json")
|
||||||
|
{
|
||||||
|
SECTION("basic_json(const CompatibleObjectType&)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
std::map<std::string, std::string> v {{"foo", "bar"}};
|
||||||
|
CHECK_NOTHROW(my_json j(v));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("basic_json(const CompatibleArrayType&)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
std::vector<std::string> v {"foo", "bar", "baz"};
|
||||||
|
CHECK_NOTHROW(my_json j(v));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("basic_json(const typename string_t::value_type*)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
CHECK_NOTHROW(my_json v("foo"));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json v("foo"), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("basic_json(const typename string_t::value_type*)")
|
||||||
|
{
|
||||||
|
next_construct_fails = false;
|
||||||
|
std::string s("foo");
|
||||||
|
CHECK_NOTHROW(my_json v(s));
|
||||||
|
next_construct_fails = true;
|
||||||
|
CHECK_THROWS_AS(my_json v(s), std::bad_alloc);
|
||||||
|
next_construct_fails = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,6 +447,10 @@ TEST_CASE("parser class")
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\\u").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\\u0").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\\u01").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\\u012").parse(), std::invalid_argument);
|
||||||
CHECK_THROWS_WITH(json::parser("\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
|
||||||
|
@ -459,6 +463,14 @@ TEST_CASE("parser class")
|
||||||
"parse error - unexpected '\"'");
|
"parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser("\"\\u").parse(),
|
||||||
|
"parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser("\"\\u0").parse(),
|
||||||
|
"parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser("\"\\u01").parse(),
|
||||||
|
"parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser("\"\\u012").parse(),
|
||||||
|
"parse error - unexpected '\"'");
|
||||||
|
|
||||||
// invalid escapes
|
// invalid escapes
|
||||||
for (int c = 1; c < 128; ++c)
|
for (int c = 1; c < 128; ++c)
|
||||||
|
|
Loading…
Reference in a new issue