2016-08-04 05:24:46 +00:00
/*
__ _____ _____ _____
__ | | __ | | | | JSON for Modern C + + ( test suite )
2019-11-17 11:09:12 +00:00
| | | __ | | | | | | version 3.7 .3
2016-08-04 05:24:46 +00:00
| _____ | _____ | _____ | _ | ___ | https : //github.com/nlohmann/json
Licensed under the MIT License < http : //opensource.org/licenses/MIT>.
2018-05-03 15:41:45 +00:00
SPDX - License - Identifier : MIT
2019-03-19 23:19:07 +00:00
Copyright ( c ) 2013 - 2019 Niels Lohmann < http : //nlohmann.me>.
2016-08-04 05:24:46 +00:00
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
*/
2019-01-13 16:41:21 +00:00
# include "doctest_compatibility.h"
2016-08-04 19:55:47 +00:00
2018-01-29 10:21:11 +00:00
# include <nlohmann/json.hpp>
2016-08-04 19:55:47 +00:00
using nlohmann : : json ;
2017-09-10 20:38:04 +00:00
# include <iostream>
2019-01-13 16:41:21 +00:00
# include <sstream>
2016-08-15 20:44:14 +00:00
# include <valarray>
2019-04-04 06:56:36 +00:00
namespace
{
2018-08-16 16:20:30 +00:00
struct SaxEventLogger : public nlohmann : : json_sax < json >
2018-02-24 17:04:07 +00:00
{
2018-08-16 16:20:30 +00:00
bool null ( ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " null() " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool boolean ( bool val ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( val ? " boolean(true) " : " boolean(false) " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool number_integer ( json : : number_integer_t val ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " number_integer( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool number_unsigned ( json : : number_unsigned_t val ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " number_unsigned( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool number_float ( json : : number_float_t , const std : : string & s ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " number_float( " + s + " ) " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool string ( std : : string & val ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " string( " + val + " ) " ) ;
return true ;
}
2019-07-05 04:13:25 +00:00
bool binary ( std : : vector < std : : uint8_t > & val )
{
std : : string binary_contents = " binary( " ;
std : : string comma_space = " " ;
for ( auto b : val )
{
binary_contents . append ( comma_space ) ;
binary_contents . append ( std : : to_string ( static_cast < int > ( b ) ) ) ;
comma_space = " , " ;
}
binary_contents . append ( " ) " ) ;
events . push_back ( binary_contents ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool start_object ( std : : size_t elements ) override
2018-02-24 17:04:07 +00:00
{
2018-02-25 17:35:16 +00:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 09:44:47 +00:00
{
events . push_back ( " start_object() " ) ;
}
else
{
events . push_back ( " start_object( " + std : : to_string ( elements ) + " ) " ) ;
}
2018-02-24 17:04:07 +00:00
return true ;
}
2018-08-16 16:20:30 +00:00
bool key ( std : : string & val ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " key( " + val + " ) " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool end_object ( ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " end_object() " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool start_array ( std : : size_t elements ) override
2018-02-24 17:04:07 +00:00
{
2018-02-25 17:35:16 +00:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 09:44:47 +00:00
{
events . push_back ( " start_array() " ) ;
}
else
{
events . push_back ( " start_array( " + std : : to_string ( elements ) + " ) " ) ;
}
2018-02-24 17:04:07 +00:00
return true ;
}
2018-08-16 16:20:30 +00:00
bool end_array ( ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " end_array() " ) ;
return true ;
}
2018-08-16 16:20:30 +00:00
bool parse_error ( std : : size_t position , const std : : string & , const json : : exception & ) override
2018-02-24 17:04:07 +00:00
{
events . push_back ( " parse_error( " + std : : to_string ( position ) + " ) " ) ;
return false ;
}
2019-03-17 11:01:49 +00:00
std : : vector < std : : string > events { } ;
2018-02-24 17:04:07 +00:00
} ;
2018-02-25 16:10:30 +00:00
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
{
2018-08-16 16:20:30 +00:00
bool start_object ( std : : size_t elements ) override
2018-02-25 16:10:30 +00:00
{
2018-08-16 16:20:30 +00:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 16:10:30 +00:00
{
events . push_back ( " start_object() " ) ;
}
else
{
events . push_back ( " start_object( " + std : : to_string ( elements ) + " ) " ) ;
}
return false ;
}
} ;
struct SaxEventLoggerExitAfterKey : public SaxEventLogger
{
2018-08-16 16:20:30 +00:00
bool key ( std : : string & val ) override
2018-02-25 16:10:30 +00:00
{
events . push_back ( " key( " + val + " ) " ) ;
return false ;
}
} ;
struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
{
2018-08-16 16:20:30 +00:00
bool start_array ( std : : size_t elements ) override
2018-02-25 16:10:30 +00:00
{
2018-08-16 16:20:30 +00:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 16:10:30 +00:00
{
events . push_back ( " start_array() " ) ;
}
else
{
events . push_back ( " start_array( " + std : : to_string ( elements ) + " ) " ) ;
}
return false ;
}
} ;
2019-04-04 06:56:36 +00:00
}
2018-02-25 16:10:30 +00:00
2016-08-04 19:55:47 +00:00
TEST_CASE ( " deserialization " )
{
2016-08-30 21:44:15 +00:00
SECTION ( " successful deserialization " )
2016-08-04 19:55:47 +00:00
{
2016-08-30 21:44:15 +00:00
SECTION ( " stream " )
{
2018-02-24 17:04:07 +00:00
std : : stringstream ss1 , ss2 , ss3 ;
2017-06-16 17:23:55 +00:00
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
2018-02-24 17:04:07 +00:00
ss3 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
2017-06-16 17:23:55 +00:00
json j = json : : parse ( ss1 ) ;
CHECK ( json : : accept ( ss2 ) ) ;
2016-08-30 21:44:15 +00:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( ss3 , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 17:04:07 +00:00
} ) ) ;
2016-08-30 21:44:15 +00:00
}
2016-08-04 19:55:47 +00:00
2016-08-31 16:07:18 +00:00
SECTION ( " string literal " )
{
auto s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j = json : : parse ( s ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( s ) ) ;
2016-08-31 16:07:18 +00:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 17:04:07 +00:00
} ) ) ;
2016-08-31 16:07:18 +00:00
}
2016-08-04 19:55:47 +00:00
2016-08-31 16:07:18 +00:00
SECTION ( " string_t " )
2016-08-30 21:44:15 +00:00
{
json : : string_t s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j = json : : parse ( s ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( s ) ) ;
2016-08-30 21:44:15 +00:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 17:04:07 +00:00
} ) ) ;
2016-08-30 21:44:15 +00:00
}
2016-08-15 20:44:14 +00:00
2016-08-30 21:44:15 +00:00
SECTION ( " operator<< " )
{
std : : stringstream ss ;
ss < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j ;
j < < ss ;
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
2016-08-04 19:55:47 +00:00
2016-08-30 21:44:15 +00:00
SECTION ( " operator>> " )
{
std : : stringstream ss ;
ss < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j ;
ss > > j ;
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
SECTION ( " user-defined string literal " )
{
CHECK ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " _json = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
2016-08-04 19:55:47 +00:00
}
2016-08-31 16:07:18 +00:00
SECTION ( " unsuccessful deserialization " )
2016-08-04 19:55:47 +00:00
{
2016-08-30 21:44:15 +00:00
SECTION ( " stream " )
{
2018-02-24 17:04:07 +00:00
std : : stringstream ss1 , ss2 , ss3 , ss4 , ss5 ;
2016-11-02 14:44:46 +00:00
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-06-16 17:23:55 +00:00
ss3 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-07-27 18:33:11 +00:00
ss4 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2018-02-24 17:04:07 +00:00
ss5 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( ss1 ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( ss2 ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( ss3 ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
2018-02-24 17:04:07 +00:00
CHECK_NOTHROW ( j_error = json : : parse ( ss4 , nullptr , false ) ) ;
2017-07-27 18:33:11 +00:00
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( ss5 , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " parse_error(29) "
2018-02-24 17:04:07 +00:00
} ) ) ;
2016-08-30 21:44:15 +00:00
}
2016-08-04 19:55:47 +00:00
2016-08-30 21:44:15 +00:00
SECTION ( " string " )
{
json : : string_t s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( s ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( s ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( s ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( s , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( s , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " parse_error(29) "
2018-02-24 17:04:07 +00:00
} ) ) ;
2016-08-30 21:44:15 +00:00
}
SECTION ( " operator<< " )
{
2016-11-02 14:44:46 +00:00
std : : stringstream ss1 , ss2 ;
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2016-08-30 21:44:15 +00:00
json j ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( j < < ss1 , json : : parse_error & ) ;
2017-03-01 20:28:44 +00:00
CHECK_THROWS_WITH ( j < < ss2 ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 21:44:15 +00:00
}
SECTION ( " operator>> " )
{
2016-11-02 14:44:46 +00:00
std : : stringstream ss1 , ss2 ;
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2016-08-30 21:44:15 +00:00
json j ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( ss1 > > j , json : : parse_error & ) ;
2017-03-01 20:28:44 +00:00
CHECK_THROWS_WITH ( ss2 > > j ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 21:44:15 +00:00
}
SECTION ( " user-defined string literal " )
{
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " _json , json : : parse_error & ) ;
2016-08-30 21:44:15 +00:00
CHECK_THROWS_WITH ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " _json ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 21:44:15 +00:00
}
2016-08-04 19:55:47 +00:00
}
2016-08-15 20:44:14 +00:00
SECTION ( " contiguous containers " )
{
2016-08-20 18:29:33 +00:00
SECTION ( " directly " )
2016-08-15 20:44:14 +00:00
{
2016-08-20 18:29:33 +00:00
SECTION ( " from std::vector " )
{
2016-08-23 20:38:05 +00:00
std : : vector < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::array " )
{
2016-08-23 20:38:05 +00:00
std : : array < uint8_t , 5 > v { { ' t ' , ' r ' , ' u ' , ' e ' } } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from array " )
{
2016-08-23 20:38:05 +00:00
uint8_t v [ ] = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
2016-08-31 16:23:46 +00:00
SECTION ( " from chars " )
{
2016-08-31 19:27:23 +00:00
uint8_t * v = new uint8_t [ 5 ] ;
2016-08-31 16:23:46 +00:00
v [ 0 ] = ' t ' ;
v [ 1 ] = ' r ' ;
v [ 2 ] = ' u ' ;
v [ 3 ] = ' e ' ;
v [ 4 ] = ' \0 ' ;
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-31 16:23:46 +00:00
delete [ ] v ;
}
2016-08-20 18:29:33 +00:00
SECTION ( " from std::string " )
{
std : : string v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::initializer_list " )
{
2016-08-23 20:38:05 +00:00
std : : initializer_list < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
2016-08-21 10:35:40 +00:00
SECTION ( " empty container " )
{
std : : vector < uint8_t > v ;
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( v ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( v ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(1) " } ) ) ;
2016-08-21 10:35:40 +00:00
}
2016-08-15 20:44:14 +00:00
}
2016-08-20 18:29:33 +00:00
SECTION ( " via iterator range " )
2016-08-15 20:44:14 +00:00
{
2016-08-20 18:29:33 +00:00
SECTION ( " from std::vector " )
{
2016-08-23 20:38:05 +00:00
std : : vector < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::array " )
{
2016-08-23 20:38:05 +00:00
std : : array < uint8_t , 5 > v { { ' t ' , ' r ' , ' u ' , ' e ' } } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from array " )
{
2016-08-23 20:38:05 +00:00
uint8_t v [ ] = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::string " )
{
std : : string v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::initializer_list " )
{
2016-08-23 20:38:05 +00:00
std : : initializer_list < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " from std::valarray " )
{
2016-08-23 20:38:05 +00:00
std : : valarray < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 18:29:33 +00:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 17:23:55 +00:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
SECTION ( " with empty range " )
{
std : : vector < uint8_t > v ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(1) " } ) ) ;
2016-08-20 18:29:33 +00:00
}
2016-08-15 20:44:14 +00:00
}
2016-08-31 22:29:42 +00:00
// these cases are required for 100% line coverage
SECTION ( " error cases " )
{
SECTION ( " case 1 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(10) " } ) ) ;
2016-08-31 22:29:42 +00:00
}
SECTION ( " case 2 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' , ' 1 ' } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(11) " } ) ) ;
2016-08-31 22:29:42 +00:00
}
2016-10-10 19:58:31 +00:00
SECTION ( " case 3 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(18) " } ) ) ;
2016-10-10 19:58:31 +00:00
}
SECTION ( " case 4 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' u ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' \\ ' } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(18) " } ) ) ;
2016-10-10 19:58:31 +00:00
}
2016-10-30 16:10:11 +00:00
SECTION ( " case 5 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xC1 } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(3) " } ) ) ;
2016-10-30 16:10:11 +00:00
}
SECTION ( " case 6 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xDF , 0x7F } ;
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( std : : begin ( v ) , std : : end ( v ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: ' \" \x7f \xdf \x7f ' " ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:10:11 +00:00
}
SECTION ( " case 7 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xDF , 0xC0 } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:10:11 +00:00
}
SECTION ( " case 8 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xE0 , 0x9F } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:10:11 +00:00
}
SECTION ( " case 9 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xEF , 0xC0 } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:10:11 +00:00
}
2016-10-30 16:46:00 +00:00
SECTION ( " case 10 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xED , 0x7F } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
SECTION ( " case 11 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF0 , 0x8F } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
SECTION ( " case 12 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF0 , 0xC0 } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
SECTION ( " case 13 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF3 , 0x7F } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
SECTION ( " case 14 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF3 , 0xC0 } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
SECTION ( " case 15 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF4 , 0x7F } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 17:23:55 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 16:46:00 +00:00
}
2017-06-20 19:09:26 +00:00
SECTION ( " case 16 " )
{
2017-06-20 20:35:31 +00:00
uint8_t v [ ] = { ' { ' , ' \" ' , ' \" ' , ' : ' , ' 1 ' , ' 1 ' } ;
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-20 19:09:26 +00:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 18:33:11 +00:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
2018-02-25 16:10:30 +00:00
CHECK ( l . events . size ( ) = = 4 ) ;
2018-02-24 17:04:07 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 16:10:30 +00:00
" start_object() " , " key() " , " number_unsigned(11) " ,
2018-02-24 17:04:07 +00:00
" parse_error(7) "
} ) ) ;
2017-06-20 19:09:26 +00:00
}
2016-08-31 22:29:42 +00:00
}
2016-08-15 20:44:14 +00:00
}
2017-09-10 20:38:04 +00:00
SECTION ( " ignoring byte-order marks " )
{
std : : string bom = " \xEF \xBB \xBF " ;
SECTION ( " BOM only " )
{
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( bom ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( bom ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal " ) ;
2017-09-10 20:38:04 +00:00
2019-07-02 19:06:42 +00:00
CHECK_THROWS_AS ( _ = json : : parse ( std : : istringstream ( bom ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( std : : istringstream ( bom ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal " ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( bom , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-04-02 19:10:48 +00:00
" parse_error(4) "
2018-02-24 17:04:07 +00:00
} ) ) ;
2017-09-10 20:38:04 +00:00
}
SECTION ( " BOM and content " )
{
CHECK ( json : : parse ( bom + " 1 " ) = = 1 ) ;
CHECK ( json : : parse ( std : : istringstream ( bom + " 1 " ) ) = = 1 ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l1 , l2 ;
CHECK ( json : : sax_parse ( std : : istringstream ( bom + " 1 " ) , & l1 ) ) ;
CHECK ( json : : sax_parse ( bom + " 1 " , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
" number_unsigned(1) "
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
" number_unsigned(1) "
} ) ) ;
2017-09-10 20:38:04 +00:00
}
SECTION ( " 2 byte of BOM " )
{
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( bom . substr ( 0 , 2 ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( bom . substr ( 0 , 2 ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: ' \xEF \xBB ' " ) ;
2017-09-10 20:38:04 +00:00
2019-07-02 19:06:42 +00:00
CHECK_THROWS_AS ( _ = json : : parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: ' \xEF \xBB ' " ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l1 , l2 ;
CHECK ( not json : : sax_parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) , & l1 ) ) ;
CHECK ( not json : : sax_parse ( bom . substr ( 0 , 2 ) , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
2018-04-02 19:10:48 +00:00
" parse_error(3) "
2018-02-24 17:04:07 +00:00
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
2018-04-02 19:10:48 +00:00
" parse_error(3) "
2018-02-24 17:04:07 +00:00
} ) ) ;
2017-09-10 20:38:04 +00:00
}
SECTION ( " 1 byte of BOM " )
{
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( bom . substr ( 0 , 1 ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( bom . substr ( 0 , 1 ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: ' \xEF ' " ) ;
2017-09-10 20:38:04 +00:00
2019-07-02 19:06:42 +00:00
CHECK_THROWS_AS ( _ = json : : parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( _ = json : : parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) ) ,
2018-10-07 20:39:17 +00:00
" [json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: ' \xEF ' " ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l1 , l2 ;
CHECK ( not json : : sax_parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) , & l1 ) ) ;
CHECK ( not json : : sax_parse ( bom . substr ( 0 , 1 ) , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
2018-04-02 19:10:48 +00:00
" parse_error(2) "
2018-02-24 17:04:07 +00:00
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
2018-04-02 19:10:48 +00:00
" parse_error(2) "
2018-02-24 17:04:07 +00:00
} ) ) ;
2017-09-10 20:38:04 +00:00
}
SECTION ( " variations " )
{
// calculate variations of each byte of the BOM to make sure
// that the BOM and only the BOM is skipped
for ( int i0 = - 1 ; i0 < 2 ; + + i0 )
{
for ( int i1 = - 1 ; i1 < 2 ; + + i1 )
{
for ( int i2 = - 1 ; i2 < 2 ; + + i2 )
{
// debug output for the variations
2018-12-23 12:56:18 +00:00
CAPTURE ( i0 )
CAPTURE ( i1 )
CAPTURE ( i2 )
2017-09-10 20:38:04 +00:00
std : : string s = " " ;
2017-09-30 09:00:26 +00:00
s . push_back ( static_cast < char > ( bom [ 0 ] + i0 ) ) ;
s . push_back ( static_cast < char > ( bom [ 1 ] + i1 ) ) ;
s . push_back ( static_cast < char > ( bom [ 2 ] + i2 ) ) ;
2017-09-10 20:38:04 +00:00
if ( i0 = = 0 and i1 = = 0 and i2 = = 0 )
{
// without any variation, we skip the BOM
CHECK ( json : : parse ( s + " null " ) = = json ( ) ) ;
CHECK ( json : : parse ( std : : istringstream ( s + " null " ) ) = = json ( ) ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s + " null " , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > (
{
" null() "
} ) ) ;
2017-09-10 20:38:04 +00:00
}
else
{
// any variation is an error
2019-07-02 19:06:42 +00:00
json _ ;
CHECK_THROWS_AS ( _ = json : : parse ( s + " null " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( _ = json : : parse ( std : : istringstream ( s + " null " ) ) , json : : parse_error & ) ;
2018-02-24 17:04:07 +00:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( s + " null " , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
2018-04-02 19:10:48 +00:00
if ( i0 ! = 0 )
2018-02-24 17:04:07 +00:00
{
2018-04-02 19:10:48 +00:00
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(1) "
} ) ) ;
}
else if ( i1 ! = 0 )
{
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(2) "
} ) ) ;
}
else
{
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(3) "
} ) ) ;
}
2017-09-10 20:38:04 +00:00
}
}
}
}
}
SECTION ( " preserve state after parsing " )
{
std : : istringstream s ( bom + " 123 456 " ) ;
json j ;
j < < s ;
CHECK ( j = = 123 ) ;
j < < s ;
CHECK ( j = = 456 ) ;
}
}
2018-02-25 16:10:30 +00:00
SECTION ( " SAX and early abort " )
{
std : : string s = " [1, [ \" string \" , 43.12], null, { \" key1 \" : true, \" key2 \" : false}] " ;
SaxEventLogger default_logger ;
SaxEventLoggerExitAfterStartObject exit_after_start_object ;
SaxEventLoggerExitAfterKey exit_after_key ;
SaxEventLoggerExitAfterStartArray exit_after_start_array ;
json : : sax_parse ( s , & default_logger ) ;
CHECK ( default_logger . events . size ( ) = = 14 ) ;
CHECK ( default_logger . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() " , " key(key1) " , " boolean(true) " , " key(key2) " ,
" boolean(false) " , " end_object() " , " end_array() "
} ) ) ;
json : : sax_parse ( s , & exit_after_start_object ) ;
CHECK ( exit_after_start_object . events . size ( ) = = 8 ) ;
CHECK ( exit_after_start_object . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() "
} ) ) ;
json : : sax_parse ( s , & exit_after_key ) ;
CHECK ( exit_after_key . events . size ( ) = = 9 ) ;
CHECK ( exit_after_key . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() " , " key(key1) "
} ) ) ;
json : : sax_parse ( s , & exit_after_start_array ) ;
CHECK ( exit_after_start_array . events . size ( ) = = 1 ) ;
CHECK ( exit_after_start_array . events = = std : : vector < std : : string > (
{
" start_array() "
} ) ) ;
}
2016-08-04 19:55:47 +00:00
}