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)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yybm[0 + yych] & 32)
 | 
			
		||||
| 
						 | 
				
			
			@ -8024,7 +8024,7 @@ basic_json_parser_6:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yybm[0 + yych] & 32)
 | 
			
		||||
| 
						 | 
				
			
			@ -8094,7 +8094,7 @@ basic_json_parser_15:
 | 
			
		|||
                    m_marker = ++m_cursor;
 | 
			
		||||
                    if ((m_limit - m_cursor) < 3)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yybm[0 + yych] & 64)
 | 
			
		||||
| 
						 | 
				
			
			@ -8187,7 +8187,7 @@ basic_json_parser_31:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
basic_json_parser_32:
 | 
			
		||||
| 
						 | 
				
			
			@ -8224,7 +8224,7 @@ basic_json_parser_36:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= 'e')
 | 
			
		||||
| 
						 | 
				
			
			@ -8368,7 +8368,7 @@ basic_json_parser_43:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= '@')
 | 
			
		||||
| 
						 | 
				
			
			@ -8404,7 +8404,7 @@ basic_json_parser_44:
 | 
			
		|||
                    m_marker = ++m_cursor;
 | 
			
		||||
                    if ((m_limit - m_cursor) < 3)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= 'D')
 | 
			
		||||
| 
						 | 
				
			
			@ -8445,7 +8445,7 @@ basic_json_parser_47:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= '/')
 | 
			
		||||
| 
						 | 
				
			
			@ -8487,7 +8487,7 @@ basic_json_parser_54:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= '@')
 | 
			
		||||
| 
						 | 
				
			
			@ -8541,7 +8541,7 @@ basic_json_parser_60:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= '@')
 | 
			
		||||
| 
						 | 
				
			
			@ -8582,7 +8582,7 @@ basic_json_parser_63:
 | 
			
		|||
                    ++m_cursor;
 | 
			
		||||
                    if (m_limit <= m_cursor)
 | 
			
		||||
                    {
 | 
			
		||||
                        fill_line_buffer();    // LCOV_EXCL_LINE;
 | 
			
		||||
                        fill_line_buffer();
 | 
			
		||||
                    }
 | 
			
		||||
                    yych = *m_cursor;
 | 
			
		||||
                    if (yych <= '@')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7854,7 +7854,7 @@ class basic_json
 | 
			
		|||
                    re2c:define:YYCURSOR  = m_cursor;
 | 
			
		||||
                    re2c:define:YYLIMIT   = m_limit;
 | 
			
		||||
                    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:indent:string    = "    ";
 | 
			
		||||
                    re2c:indent:top       = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,13 +28,14 @@ SOFTWARE.
 | 
			
		|||
 | 
			
		||||
#include "catch.hpp"
 | 
			
		||||
 | 
			
		||||
#define private public
 | 
			
		||||
#include "json.hpp"
 | 
			
		||||
using nlohmann::json;
 | 
			
		||||
 | 
			
		||||
// special test case to check if memory is leaked if constructor throws
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
struct my_allocator : std::allocator<T>
 | 
			
		||||
struct bad_allocator : std::allocator<T>
 | 
			
		||||
{
 | 
			
		||||
    template<class... Args>
 | 
			
		||||
    void construct(T*, Args&& ...)
 | 
			
		||||
| 
						 | 
				
			
			@ -48,16 +49,186 @@ TEST_CASE("bad_alloc")
 | 
			
		|||
    SECTION("bad_alloc")
 | 
			
		||||
    {
 | 
			
		||||
        // 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::string,
 | 
			
		||||
              bool,
 | 
			
		||||
              std::int64_t,
 | 
			
		||||
              std::uint64_t,
 | 
			
		||||
              double,
 | 
			
		||||
              my_allocator>;
 | 
			
		||||
              bad_allocator>;
 | 
			
		||||
 | 
			
		||||
        // 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("\"\\u01\"").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(),
 | 
			
		||||
                          "parse error - unexpected '\"'");
 | 
			
		||||
        CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
 | 
			
		||||
| 
						 | 
				
			
			@ -459,6 +463,14 @@ TEST_CASE("parser class")
 | 
			
		|||
                          "parse error - unexpected '\"'");
 | 
			
		||||
        CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
 | 
			
		||||
                          "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
 | 
			
		||||
        for (int c = 1; c < 128; ++c)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue