xml.hpp
Go to the documentation of this file.
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_ARCHIVES_XML_HPP_
#define CEREAL_ARCHIVES_XML_HPP_
#include <cereal/cereal.hpp>
#include <cereal/details/util.hpp>
#include <cereal/external/rapidxml/rapidxml.hpp>
#include <cereal/external/rapidxml/rapidxml_print.hpp>
#include <cereal/external/base64.hpp>
#include <sstream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <cstring>
#include <cmath>
namespace cereal
{
namespace xml_detail
{
#ifndef CEREAL_XML_STRING_VALUE
#define CEREAL_XML_STRING_VALUE "cereal"
#endif // CEREAL_XML_STRING_VALUE
static const char * CEREAL_XML_STRING = CEREAL_XML_STRING_VALUE;
inline bool isWhitespace( char c )
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
}
// ######################################################################
class XMLOutputArchive : public OutputArchive<XMLOutputArchive>, public traits::TextArchive
{
public:
class Options
{
public:
static Options Default(){ return Options(); }
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, false ); }
explicit Options( int precision = std::numeric_limits<double>::max_digits10,
bool indent = true,
bool outputType = false ) :
itsPrecision( precision ),
itsIndent( indent ),
itsOutputType( outputType ) { }
private:
friend class XMLOutputArchive;
int itsPrecision;
bool itsIndent;
bool itsOutputType;
};
XMLOutputArchive( std::ostream & stream, Options const & options = Options::Default() ) :
OutputArchive<XMLOutputArchive>(this),
itsStream(stream),
itsOutputType( options.itsOutputType ),
itsIndent( options.itsIndent )
{
// rapidxml will delete all allocations when xml_document is cleared
auto node = itsXML.allocate_node( rapidxml::node_declaration );
node->append_attribute( itsXML.allocate_attribute( "version", "1.0" ) );
node->append_attribute( itsXML.allocate_attribute( "encoding", "utf-8" ) );
itsXML.append_node( node );
// allocate root node
auto root = itsXML.allocate_node( rapidxml::node_element, xml_detail::CEREAL_XML_STRING );
itsXML.append_node( root );
itsNodes.emplace( root );
// set attributes on the streams
itsStream << std::boolalpha;
itsStream.precision( options.itsPrecision );
itsOS << std::boolalpha;
itsOS.precision( options.itsPrecision );
}
~XMLOutputArchive()
{
const int flags = itsIndent ? 0x0 : rapidxml::print_no_indenting;
rapidxml::print( itsStream, itsXML, flags );
itsXML.clear();
}
void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
{
itsNodes.top().name = name;
startNode();
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
saveValue( base64string );
if( itsOutputType )
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
finishNode();
};
void startNode()
{
// generate a name for this new node
const auto nameString = itsNodes.top().getValueName();
// allocate strings for all of the data in the XML object
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
// insert into the XML
auto node = itsXML.allocate_node( rapidxml::node_element, namePtr, nullptr, nameString.size() );
itsNodes.top().node->append_node( node );
itsNodes.emplace( node );
}
void finishNode()
{
itsNodes.pop();
}
void setNextName( const char * name )
{
itsNodes.top().name = name;
}
template <class T> inline
void saveValue( T const & value )
{
itsOS.clear(); itsOS.seekp( 0, std::ios::beg );
itsOS << value << std::ends;
const auto strValue = itsOS.str();
// If the first or last character is a whitespace, add xml:space attribute
// the string always contains a '\0' added by std::ends, so the last character is at len-2 and an 'empty'
// string has a length of 1 or lower
const auto len = strValue.length();
if ( len > 1 && ( xml_detail::isWhitespace( strValue[0] ) || xml_detail::isWhitespace( strValue[len - 2] ) ) )
{
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "xml:space", "preserve" ) );
}
// allocate strings for all of the data in the XML object
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str(), itsOS.str().length() + 1 );
// insert into the XML
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
}
void saveValue( uint8_t const & value )
{
saveValue( static_cast<uint32_t>( value ) );
}
void saveValue( int8_t const & value )
{
saveValue( static_cast<int32_t>( value ) );
}
template <class T> inline
void insertType()
{
if( !itsOutputType )
return;
// generate a name for this new node
const auto nameString = util::demangledName<T>();
// allocate strings for all of the data in the XML object
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) );
}
void appendAttribute( const char * name, const char * value )
{
auto namePtr = itsXML.allocate_string( name );
auto valuePtr = itsXML.allocate_string( value );
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) );
}
protected:
struct NodeInfo
{
NodeInfo( rapidxml::xml_node<> * n = nullptr,
const char * nm = nullptr ) :
node( n ),
counter( 0 ),
name( nm )
{ }
rapidxml::xml_node<> * node;
size_t counter;
const char * name;
std::string getValueName()
{
if( name )
{
auto n = name;
name = nullptr;
return {n};
}
else
return "value" + std::to_string( counter++ ) + "\0";
}
}; // NodeInfo
private:
std::ostream & itsStream;
rapidxml::xml_document<> itsXML;
std::stack<NodeInfo> itsNodes;
std::ostringstream itsOS;
bool itsOutputType;
bool itsIndent;
}; // XMLOutputArchive
// ######################################################################
class XMLInputArchive : public InputArchive<XMLInputArchive>, public traits::TextArchive
{
public:
XMLInputArchive( std::istream & stream ) :
InputArchive<XMLInputArchive>( this ),
itsData( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() )
{
try
{
itsData.push_back('\0'); // rapidxml will do terrible things without the data being null terminated
itsXML.parse<rapidxml::parse_trim_whitespace | rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
}
catch( rapidxml::parse_error const & )
{
//std::cerr << "-----Original-----" << std::endl;
//stream.seekg(0);
//std::cout << std::string( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() ) << std::endl;
//std::cerr << "-----Error-----" << std::endl;
//std::cerr << e.what() << std::endl;
//std::cerr << e.where<char>() << std::endl;
throw Exception("XML Parsing failed - likely due to invalid characters or invalid naming");
}
// Parse the root
auto root = itsXML.first_node( xml_detail::CEREAL_XML_STRING );
if( root == nullptr )
throw Exception("Could not detect cereal root node - likely due to empty or invalid input");
else
itsNodes.emplace( root );
}
void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
{
setNextName( name );
startNode();
std::string encoded;
loadValue( encoded );
auto decoded = base64::decode( encoded );
if( size != decoded.size() )
throw Exception("Decoded binary data size does not match specified size");
std::memcpy( data, decoded.data(), decoded.size() );
finishNode();
};
void startNode()
{
auto next = itsNodes.top().child; // By default we would move to the next child node
auto const expectedName = itsNodes.top().name; // this is the expected name from the NVP, if provided
// If we were given an NVP name, look for it in the current level of the document.
// We only need to do this if either we have exhausted the siblings of the current level or
// the NVP name does not match the name of the node we would normally read next
if( expectedName && ( next == nullptr || std::strcmp( next->name(), expectedName ) != 0 ) )
{
next = itsNodes.top().search( expectedName );
if( next == nullptr )
throw Exception("XML Parsing failed - provided NVP not found");
}
itsNodes.emplace( next );
}
void finishNode()
{
// remove current
itsNodes.pop();
// advance parent
itsNodes.top().advance();
// Reset name
itsNodes.top().name = nullptr;
}
const char * getNodeName() const
{
return itsNodes.top().node->name();
}
void setNextName( const char * name )
{
itsNodes.top().name = name;
}
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
std::is_same<T, bool>::value> = traits::sfinae> inline
void loadValue( T & value )
{
std::istringstream is( itsNodes.top().node->value() );
is.setf( std::ios::boolalpha );
is >> value;
}
template <class T, traits::EnableIf<std::is_integral<T>::value,
!std::is_same<T, bool>::value,
sizeof(T) == sizeof(char)> = traits::sfinae> inline
void loadValue( T & value )
{
value = *reinterpret_cast<T*>( itsNodes.top().node->value() );
}
void loadValue( int8_t & value )
{
int32_t val; loadValue( val ); value = static_cast<int8_t>( val );
}
void loadValue( uint8_t & value )
{
uint32_t val; loadValue( val ); value = static_cast<uint8_t>( val );
}
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
!std::is_same<T, bool>::value,
!std::is_same<T, char>::value,
!std::is_same<T, unsigned char>::value,
sizeof(T) < sizeof(long long)> = traits::sfinae> inline
void loadValue( T & value )
{
value = static_cast<T>( std::stoul( itsNodes.top().node->value() ) );
}
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
!std::is_same<T, bool>::value,
sizeof(T) >= sizeof(long long)> = traits::sfinae> inline
void loadValue( T & value )
{
value = static_cast<T>( std::stoull( itsNodes.top().node->value() ) );
}
template <class T, traits::EnableIf<std::is_signed<T>::value,
!std::is_same<T, char>::value,
sizeof(T) <= sizeof(int)> = traits::sfinae> inline
void loadValue( T & value )
{
value = static_cast<T>( std::stoi( itsNodes.top().node->value() ) );
}
template <class T, traits::EnableIf<std::is_signed<T>::value,
(sizeof(T) > sizeof(int)),
sizeof(T) <= sizeof(long)> = traits::sfinae> inline
void loadValue( T & value )
{
value = static_cast<T>( std::stol( itsNodes.top().node->value() ) );
}
template <class T, traits::EnableIf<std::is_signed<T>::value,
(sizeof(T) > sizeof(long)),
sizeof(T) <= sizeof(long long)> = traits::sfinae> inline
void loadValue( T & value )
{
value = static_cast<T>( std::stoll( itsNodes.top().node->value() ) );
}
void loadValue( float & value )
{
try
{
value = std::stof( itsNodes.top().node->value() );
}
catch( std::out_of_range const & )
{
// special case for denormalized values
std::istringstream is( itsNodes.top().node->value() );
is >> value;
if( std::fpclassify( value ) != FP_SUBNORMAL )
throw;
}
}
void loadValue( double & value )
{
try
{
value = std::stod( itsNodes.top().node->value() );
}
catch( std::out_of_range const & )
{
// special case for denormalized values
std::istringstream is( itsNodes.top().node->value() );
is >> value;
if( std::fpclassify( value ) != FP_SUBNORMAL )
throw;
}
}
void loadValue( long double & value )
{
try
{
value = std::stold( itsNodes.top().node->value() );
}
catch( std::out_of_range const & )
{
// special case for denormalized values
std::istringstream is( itsNodes.top().node->value() );
is >> value;
if( std::fpclassify( value ) != FP_SUBNORMAL )
throw;
}
}
template<class CharT, class Traits, class Alloc> inline
void loadValue( std::basic_string<CharT, Traits, Alloc> & str )
{
std::basic_istringstream<CharT, Traits> is( itsNodes.top().node->value() );
str.assign( std::istreambuf_iterator<CharT, Traits>( is ),
std::istreambuf_iterator<CharT, Traits>() );
}
template <class T> inline
void loadSize( T & value )
{
value = getNumChildren( itsNodes.top().node );
}
protected:
static size_t getNumChildren( rapidxml::xml_node<> * node )
{
size_t size = 0;
node = node->first_node(); // get first child
while( node != nullptr )
{
++size;
node = node->next_sibling();
}
return size;
}
struct NodeInfo
{
NodeInfo( rapidxml::xml_node<> * n = nullptr ) :
node( n ),
child( n->first_node() ),
size( XMLInputArchive::getNumChildren( n ) ),
name( nullptr )
{ }
void advance()
{
if( size > 0 )
{
--size;
child = child->next_sibling();
}
}
rapidxml::xml_node<> * search( const char * searchName )
{
if( searchName )
{
size_t new_size = XMLInputArchive::getNumChildren( node );
const size_t name_size = rapidxml::internal::measure( searchName );
for( auto new_child = node->first_node(); new_child != nullptr; new_child = new_child->next_sibling() )
{
if( rapidxml::internal::compare( new_child->name(), new_child->name_size(), searchName, name_size, true ) )
{
size = new_size;
child = new_child;
return new_child;
}
--new_size;
}
}
return nullptr;
}
rapidxml::xml_node<> * node;
rapidxml::xml_node<> * child;
size_t size;
const char * name;
}; // NodeInfo
private:
std::vector<char> itsData;
rapidxml::xml_document<> itsXML;
std::stack<NodeInfo> itsNodes;
};
// ######################################################################
// XMLArchive prologue and epilogue functions
// ######################################################################
// ######################################################################
template <class T> inline
void prologue( XMLOutputArchive &, NameValuePair<T> const & )
{ }
template <class T> inline
void prologue( XMLInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
template <class T> inline
void epilogue( XMLOutputArchive &, NameValuePair<T> const & )
{ }
template <class T> inline
void epilogue( XMLInputArchive &, NameValuePair<T> const & )
{ }
// ######################################################################
template <class T> inline
void prologue( XMLOutputArchive & ar, SizeTag<T> const & )
{
ar.appendAttribute( "size", "dynamic" );
}
template <class T> inline
void prologue( XMLInputArchive &, SizeTag<T> const & )
{ }
template <class T> inline
void epilogue( XMLOutputArchive &, SizeTag<T> const & )
{ }
template <class T> inline
void epilogue( XMLInputArchive &, SizeTag<T> const & )
{ }
// ######################################################################
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
void prologue( XMLOutputArchive & ar, T const & )
{
ar.startNode();
ar.insertType<T>();
}
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
void prologue( XMLInputArchive & ar, T const & )
{
ar.startNode();
}
// ######################################################################
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
void epilogue( XMLOutputArchive & ar, T const & )
{
ar.finishNode();
}
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
void epilogue( XMLInputArchive & ar, T const & )
{
ar.finishNode();
}
// ######################################################################
// Common XMLArchive serialization functions
// ######################################################################
template <class T> inline
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive & ar, NameValuePair<T> const & t )
{
ar.setNextName( t.name );
ar( t.value );
}
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, NameValuePair<T> & t )
{
ar.setNextName( t.name );
ar( t.value );
}
// ######################################################################
template <class T> inline
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive &, SizeTag<T> const & )
{ }
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, SizeTag<T> & st )
{
ar.loadSize( st.size );
}
// ######################################################################
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, T const & t)
{
ar.saveValue( t );
}
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, T & t)
{
ar.loadValue( t );
}
// ######################################################################
template<class CharT, class Traits, class Alloc> inline
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
{
ar.saveValue( str );
}
template<class CharT, class Traits, class Alloc> inline
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
{
ar.loadValue( str );
}
} // namespace cereal
// register archives for polymorphic support
CEREAL_REGISTER_ARCHIVE(cereal::XMLOutputArchive)
CEREAL_REGISTER_ARCHIVE(cereal::XMLInputArchive)
// tie input and output archives together
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::XMLInputArchive, cereal::XMLOutputArchive)
#endif // CEREAL_ARCHIVES_XML_HPP_
cereal::XMLOutputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: xml.hpp:220
cereal::XMLOutputArchive::~XMLOutputArchive
~XMLOutputArchive()
Destructor, flushes the XML.
Definition: xml.hpp:161
cereal::XMLOutputArchive::Options::Options
Options(int precision=std::numeric_limits< double >::max_digits10, bool indent=true, bool outputType=false)
Specify specific options for the XMLOutputArchive.
Definition: xml.hpp:117
CEREAL_SETUP_ARCHIVE_TRAITS
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive)
Sets up traits that relate an input archive to an output archive.
Definition: traits.hpp:169
cereal::xml_detail::isWhitespace
bool isWhitespace(char c)
Returns true if the character is whitespace.
Definition: xml.hpp:61
cereal::XMLInputArchive::NodeInfo::child
rapidxml::xml_node * child
A pointer to its current child.
Definition: xml.hpp:706
cereal::SizeTag
A wrapper around size metadata.
Definition: helpers.hpp:250
cereal::XMLInputArchive::XMLInputArchive
XMLInputArchive(std::istream &stream)
Construct, reading in from the provided stream.
Definition: xml.hpp:380
cereal::XMLInputArchive::loadValue
void loadValue(std::basic_string< CharT, Traits, Alloc > &str)
Loads a string from the current node from the current top node.
Definition: xml.hpp:625
cereal::XMLInputArchive::NodeInfo::size
size_t size
The remaining number of children for this node.
Definition: xml.hpp:707
cereal::prologue
void prologue(JSONOutputArchive &, NameValuePair< T > const &)
Prologue for NVPs for JSON archives.
Definition: json.hpp:702
cereal::XMLOutputArchive::Options::NoIndent
static Options NoIndent()
Default options with no indentation.
Definition: xml.hpp:111
CEREAL_XML_STRING_VALUE
#define CEREAL_XML_STRING_VALUE
The default name for the root node in a cereal xml archive.
Definition: xml.hpp:54
std
STL namespace.
cereal::XMLInputArchive::NodeInfo::node
rapidxml::xml_node * node
A pointer to this node.
Definition: xml.hpp:705
cereal::traits::TextArchive
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1266
cereal::InputArchive
The base input archive class.
Definition: cereal.hpp:584
cereal::XMLOutputArchive::saveValue
void saveValue(T const &value)
Saves some data, encoded as a string, into the current top level node.
Definition: xml.hpp:230
cereal::XMLInputArchive::getNodeName
const char * getNodeName() const
Definition: xml.hpp:483
cereal::XMLInputArchive::NodeInfo::advance
void advance()
Advances to the next sibling node of the child.
Definition: xml.hpp:670
cereal::XMLOutputArchive::NodeInfo
A struct that contains metadata about a node.
Definition: xml.hpp:291
cereal::XMLOutputArchive::insertType
void insertType()
Causes the type to be appended as an attribute to the most recently made node if output type is set t...
Definition: xml.hpp:267
cereal::XMLInputArchive::NodeInfo
A struct that contains metadata about a node.
Definition: xml.hpp:659
cereal::XMLInputArchive::NodeInfo::search
rapidxml::xml_node * search(const char *searchName)
Searches for a child with the given name in this node.
Definition: xml.hpp:682
cereal::XMLInputArchive::setNextName
void setNextName(const char *name)
Sets the name for the next node created with startNode.
Definition: xml.hpp:489
cereal::XMLOutputArchive::NodeInfo::getValueName
std::string getValueName()
Gets the name for the next child node created from this node.
Definition: xml.hpp:308
cereal::XMLInputArchive::loadValue
void loadValue(long double &value)
Loads a type best represented as a long double from the current top node.
Definition: xml.hpp:607
cereal::traits::has_minimal_input_serialization
Definition: traits.hpp:1002
cereal::XMLInputArchive::loadValue
void loadValue(int8_t &value)
Load an int8_t from the current top node (ensures we parse entire number)
Definition: xml.hpp:514
cereal::XMLOutputArchive::saveValue
void saveValue(int8_t const &value)
Overload for int8_t prevents them from being serialized as characters.
Definition: xml.hpp:260
cereal::XMLOutputArchive::NodeInfo::node
rapidxml::xml_node * node
A pointer to this node.
Definition: xml.hpp:300
cereal::XMLOutputArchive::saveBinaryValue
void saveBinaryValue(const void *data, size_t size, const char *name=nullptr)
Saves some binary data, encoded as a base64 string, with an optional name.
Definition: xml.hpp:172
cereal::XMLOutputArchive::NodeInfo::counter
size_t counter
The counter for naming child nodes.
Definition: xml.hpp:301
cereal::XMLOutputArchive
An output archive designed to save data to XML.
Definition: xml.hpp:96
cereal::traits::has_minimal_output_serialization
Definition: traits.hpp:990
cereal::XMLInputArchive::NodeInfo::name
const char * name
The NVP name for next next child node.
Definition: xml.hpp:708
cereal
Definition: access.hpp:39
CEREAL_REGISTER_ARCHIVE
#define CEREAL_REGISTER_ARCHIVE(Archive)
Registers a specific Archive type with cereal.
Definition: cereal.hpp:141
cereal::XMLInputArchive
An output archive designed to load data from XML.
Definition: xml.hpp:368
cereal::XMLOutputArchive::startNode
void startNode()
Creates a new node that is a child of the node at the top of the stack.
Definition: xml.hpp:199
util.hpp
Internal misc utilities.
cereal.hpp
Main cereal functionality.
cereal::NameValuePair
For holding name value pairs.
Definition: helpers.hpp:135
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
cereal::XMLInputArchive::loadSize
void loadSize(T &value)
Loads the size of the current top node.
Definition: xml.hpp:635
cereal::XMLOutputArchive::finishNode
void finishNode()
Designates the most recently added node as finished.
Definition: xml.hpp:214
cereal::XMLInputArchive::finishNode
void finishNode()
Finishes reading the current node.
Definition: xml.hpp:469
cereal::OutputArchive
The base output archive class.
Definition: cereal.hpp:234
cereal::XMLInputArchive::value
value
Loads a type best represented as an int from the current top node.
Definition: xml.hpp:600
cereal::XMLOutputArchive::appendAttribute
void appendAttribute(const char *name, const char *value)
Appends an attribute to the current top level node.
Definition: xml.hpp:282
cereal::XMLInputArchive::getNumChildren
static size_t getNumChildren(rapidxml::xml_node<> *node)
Gets the number of children (usually interpreted as size) for the specified node. ...
Definition: xml.hpp:642
CEREAL_SAVE_FUNCTION_NAME
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:65
cereal::XMLOutputArchive::Options::Default
static Options Default()
Default options.
Definition: xml.hpp:108
cereal::XMLInputArchive::startNode
void startNode()
Prepares to start reading the next node.
Definition: xml.hpp:449
cereal::XMLOutputArchive::NodeInfo::name
const char * name
The name for the next child node.
Definition: xml.hpp:302
cereal::XMLInputArchive::loadValue
void loadValue(T &value)
Loads a bool from the current top node.
Definition: xml.hpp:497
cereal::epilogue
void epilogue(JSONOutputArchive &, NameValuePair< T > const &)
Epilogue for NVPs for JSON archives.
Definition: json.hpp:714
cereal::XMLInputArchive::loadBinaryValue
void loadBinaryValue(void *data, size_t size, const char *name=nullptr)
Loads some binary data, encoded as a base64 string, optionally specified by some name.
Definition: xml.hpp:415
cereal::XMLOutputArchive::Options
A class containing various advanced options for the XML archive.
Definition: xml.hpp:104
cereal::Exception
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
cereal::XMLInputArchive::loadValue
void loadValue(uint8_t &value)
Load a uint8_t from the current top node (ensures we parse entire number)
Definition: xml.hpp:520
cereal::XMLOutputArchive::saveValue
void saveValue(uint8_t const &value)
Overload for uint8_t prevents them from being serialized as characters.
Definition: xml.hpp:254
cereal::XMLOutputArchive::XMLOutputArchive
XMLOutputArchive(std::ostream &stream, Options const &options=Options::Default())
Construct, outputting to the provided stream upon destruction.
Definition: xml.hpp:136