29 #ifndef CEREAL_ARCHIVES_XML_HPP_
30 #define CEREAL_ARCHIVES_XML_HPP_
32 #include <cereal/cereal.hpp>
33 #include <cereal/details/util.hpp>
37 #include <cereal/external/base64.hpp>
49 static const char * CEREAL_XML_STRING =
"cereal";
63 XMLOutputArchive(std::ostream & stream,
size_t precision = 10,
bool outputType =
false ) :
66 itsOutputType( outputType )
69 auto node = itsXML.
allocate_node( rapidxml::node_declaration );
75 auto root = itsXML.
allocate_node( rapidxml::node_element, xml_detail::CEREAL_XML_STRING );
77 itsNodes.emplace( root );
80 itsStream << std::boolalpha;
81 itsStream.precision( precision );
82 itsOS << std::boolalpha;
83 itsOS.precision( precision );
101 const auto nameString = itsNodes.top().getValueName();
104 auto namePtr = itsXML.
allocate_string( nameString.data(), nameString.size() );
107 auto node = itsXML.
allocate_node( rapidxml::node_element, namePtr,
nullptr, nameString.size() );
108 itsNodes.top().node->append_node( node );
109 itsNodes.emplace( node );
121 itsNodes.top().name = name;
128 template <
class T>
inline
131 itsOS.clear(); itsOS.seekp(0);
132 itsOS << value << std::ends;
138 itsNodes.top().node->append_node( itsXML.
allocate_node( rapidxml::node_data,
nullptr, dataPtr ) );
144 saveValue( static_cast<uint32_t>( value ) );
152 itsNodes.top().name = name;
156 auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
160 itsNodes.top().node->append_attribute( itsXML.
allocate_attribute(
"type",
"cereal binary data" ) );
166 template <
class T>
inline
173 const auto nameString = util::demangledName<T>();
176 auto namePtr = itsXML.
allocate_string( nameString.data(), nameString.size() );
178 itsNodes.top().node->append_attribute( itsXML.
allocate_attribute(
"type", namePtr ) );
186 const char * nm =
nullptr ) :
209 return "value" + std::to_string(
counter++ ) +
"\0";
214 std::ostream & itsStream;
216 std::stack<NodeInfo> itsNodes;
217 std::ostringstream itsOS;
234 itsData( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() )
238 itsXML.
parse<rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>(
reinterpret_cast<char *
>( itsData.data() ) );
242 throw Exception(
"XML Parsing failed - likely due to invalid characters or invalid naming");
248 auto root = itsXML.
first_node( xml_detail::CEREAL_XML_STRING );
249 itsNodes.emplace( root );
255 itsNodes.emplace( itsNodes.top().child );
265 itsNodes.top().advance();
269 template <
class T>
inline
272 std::istringstream is( itsNodes.top().node->value() );
273 is.setf( std::ios::boolalpha );
278 template<
class CharT,
class Traits,
class Alloc>
inline
279 void loadValue( std::basic_string<CharT, Traits, Alloc> & str )
281 std::basic_istringstream<CharT, Traits> is( itsNodes.top().node->value() );
283 str.assign( std::istreambuf_iterator<CharT, Traits>( is ),
284 std::istreambuf_iterator<CharT, Traits>() );
296 auto decoded = base64::decode( encoded );
298 if( size != decoded.size() )
299 throw Exception(
"Decoded binary data size does not match specified size");
301 std::memcpy( data, decoded.data(), decoded.size() );
307 template <
class T>
inline
317 node = node->first_node();
319 while( node !=
nullptr )
322 node = node->next_sibling();
334 child( n ? n->first_node() : nullptr ),
353 std::vector<uint8_t> itsData;
355 std::stack<NodeInfo> itsNodes;
371 void prologue( XMLInputArchive &, NameValuePair<T>
const & )
378 void epilogue( XMLOutputArchive &, NameValuePair<T>
const & )
383 void epilogue( XMLInputArchive &, NameValuePair<T>
const & )
390 void prologue( XMLOutputArchive &, SizeTag<T>
const & )
394 void prologue( XMLInputArchive &, SizeTag<T>
const & )
400 void epilogue( XMLOutputArchive &, SizeTag<T>
const & )
404 void epilogue( XMLInputArchive &, SizeTag<T>
const & )
412 void prologue( XMLOutputArchive & ar, T
const & )
420 void prologue( XMLInputArchive & ar, T
const & )
429 void epilogue( XMLOutputArchive & ar, T
const & )
436 void epilogue( XMLInputArchive & ar, T
const & )
446 template <
class T>
inline
447 void save( XMLOutputArchive & ar, NameValuePair<T>
const & t )
449 ar.setNextName( t.name );
454 template <
class T>
inline
455 void load( XMLInputArchive & ar, NameValuePair<T> & t )
462 template <
class T>
inline
463 void save( XMLOutputArchive &, SizeTag<T>
const & )
467 template <
class T>
inline
468 void load( XMLInputArchive & ar, SizeTag<T> & st )
470 ar.loadSize( st.size );
475 template<
class T>
inline
476 typename std::enable_if<std::is_arithmetic<T>::value,
void>::type
477 save(XMLOutputArchive & ar, T
const & t)
483 template<
class T>
inline
484 typename std::enable_if<std::is_arithmetic<T>::value,
void>::type
485 load(XMLInputArchive & ar, T & t)
492 template<
class CharT,
class Traits,
class Alloc>
inline
493 void save(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc>
const & str)
499 template<
class CharT,
class Traits,
class Alloc>
inline
500 void load(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
510 #endif // CEREAL_ARCHIVES_XML_HPP_