mirror of
https://github.com/RPCS3/cereal.git
synced 2025-01-06 02:28:24 +00:00
Extended the fix for issue #109 and added a test.
This commit is contained in:
parent
b0d45bd565
commit
16bf75dedf
@ -238,8 +238,11 @@ namespace cereal
|
||||
itsOS.clear(); itsOS.seekp( 0, std::ios::beg );
|
||||
itsOS << value << std::ends;
|
||||
|
||||
// workaround rapidxml restriction on whitespace handling.
|
||||
auto encoded = encode_cdata( itsOS.str() );
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str() );
|
||||
auto dataPtr = itsXML.allocate_string( encoded.c_str() );
|
||||
|
||||
// allocate cdata and set its value
|
||||
auto cdata = itsXML.allocate_node( rapidxml::node_cdata );
|
||||
@ -317,6 +320,34 @@ namespace cereal
|
||||
}
|
||||
}; // NodeInfo
|
||||
|
||||
//! Encode only & and > in cdata text
|
||||
/* Normally CDATA when saved to XML should not be changed in any way
|
||||
but since rapidxml doesn't handle xml:space attribute in XML elements then
|
||||
we use CDATA and do escaping of non-allowed characters manually. */
|
||||
std::string encode_cdata( std::string const & text )
|
||||
{
|
||||
std::string res;
|
||||
res.reserve( text.size() );
|
||||
|
||||
for( auto c : text )
|
||||
{
|
||||
if( c == '&' )
|
||||
{
|
||||
res.append( "&" );
|
||||
}
|
||||
else if( c == '>' )
|
||||
{
|
||||
res.append( ">" );
|
||||
}
|
||||
else
|
||||
{
|
||||
res.append( 1, c );
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
@ -594,8 +625,8 @@ namespace cereal
|
||||
|
||||
std::basic_istringstream<CharT, Traits> is( first_node->value() );
|
||||
|
||||
str.assign( std::istreambuf_iterator<CharT, Traits>( is ),
|
||||
std::istreambuf_iterator<CharT, Traits>() );
|
||||
str = decode_cdata<CharT, Traits, Alloc>( std::istreambuf_iterator<CharT, Traits>( is ),
|
||||
std::istreambuf_iterator<CharT, Traits>() );
|
||||
}
|
||||
|
||||
//! Loads the size of the current top node
|
||||
@ -676,6 +707,44 @@ namespace cereal
|
||||
const char * name; //!< The NVP name for next next child node
|
||||
}; // NodeInfo
|
||||
|
||||
//! Decode & and > characters in cdata
|
||||
/* For details see explanation for XMLOutputArchive::encode_cdata(). */
|
||||
template<class CharT, class Traits, class Alloc>
|
||||
std::basic_string<CharT, Traits, Alloc> decode_cdata( std::istreambuf_iterator<CharT, Traits> start,
|
||||
const std::istreambuf_iterator<CharT, Traits>& end )
|
||||
{
|
||||
std::basic_string<CharT, Traits, Alloc> res;
|
||||
|
||||
for( ; start != end; ++start )
|
||||
{
|
||||
if( *start == '&' )
|
||||
{
|
||||
const auto first = *( ++start );
|
||||
const auto second = *( ++start );
|
||||
const auto third = *( ++start );
|
||||
|
||||
if( first == 'g' && second == 't' && third == ';' )
|
||||
{
|
||||
res.append( 1, '>' );
|
||||
}
|
||||
else if( first == 'a' && second == 'm' && third == 'p' && *( ++start ) == ';' )
|
||||
{
|
||||
res.append( 1, '&' );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception("Cannot decode cdata value");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.append( 1, *start );
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
@ -125,3 +125,43 @@ BOOST_AUTO_TEST_CASE( json_string_basic )
|
||||
test_string_basic<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
|
||||
}
|
||||
|
||||
template <class IArchive, class OArchive, class T, size_t N, size_t M>
|
||||
void test_string_for_array(T (&strings)[N][M])
|
||||
{
|
||||
for(size_t i=0; i<N; ++i)
|
||||
{
|
||||
std::basic_string<T> o_string = strings[i];
|
||||
|
||||
std::ostringstream os;
|
||||
{
|
||||
OArchive oar(os);
|
||||
oar(o_string);
|
||||
}
|
||||
|
||||
std::basic_string<T> i_string;
|
||||
|
||||
std::istringstream is(os.str());
|
||||
{
|
||||
IArchive iar(is);
|
||||
iar(i_string);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(i_string, o_string);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( xml_string_issue109 )
|
||||
{
|
||||
char strings[][20] = {
|
||||
"some text",
|
||||
" some text ",
|
||||
" ",
|
||||
" text ",
|
||||
" ]]> ",
|
||||
" > > ]]> ",
|
||||
" < <]>] < ",
|
||||
" & & "
|
||||
};
|
||||
|
||||
test_string_for_array<cereal::XMLInputArchive, cereal::XMLOutputArchive>(strings);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user