mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
working on input xml
This commit is contained in:
@@ -28,49 +28,35 @@
|
|||||||
#define CEREAL_ARCHIVES_XML_HPP_
|
#define CEREAL_ARCHIVES_XML_HPP_
|
||||||
|
|
||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
|
#include <cereal/details/util.hpp>
|
||||||
|
|
||||||
#include <cereal/external/rapidxml/rapidxml.hpp>
|
#include <cereal/external/rapidxml/rapidxml.hpp>
|
||||||
#include <cereal/external/rapidxml/rapidxml_print.hpp>
|
#include <cereal/external/rapidxml/rapidxml_print.hpp>
|
||||||
#include <cereal/external/base64.hpp>
|
#include <cereal/external/base64.hpp>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct XMLHelper
|
|
||||||
{
|
|
||||||
const char * popName()
|
|
||||||
{
|
|
||||||
if( names.empty() )
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto name = names.top();
|
|
||||||
names.pop();
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stack<const char *> names;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
//! An output archive designed to save data to XML
|
//! An output archive designed to save data to XML
|
||||||
class XMLOutputArchive : public OutputArchive<XMLOutputArchive, AllowEmptyClassElision>
|
class XMLOutputArchive : public OutputArchive<XMLOutputArchive>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! Construct, outputting to the provided stream
|
//! Construct, outputting to the provided stream
|
||||||
/*! @param stream The stream to output to. Can be a stringstream, a file stream, or
|
/*! @param stream The stream to output to. Can be a stringstream, a file stream, or
|
||||||
even cout!
|
even cout!
|
||||||
@param precision The precision for floating point output */
|
@param precision The precision for floating point output
|
||||||
XMLOutputArchive(std::ostream & stream, size_t precision = 10 ) :
|
@param outputType Controls whether type information will be printed in attributes */
|
||||||
OutputArchive<XMLOutputArchive, AllowEmptyClassElision>(this),
|
XMLOutputArchive(std::ostream & stream, size_t precision = 10, bool outputType = false ) :
|
||||||
itsStream(stream)
|
OutputArchive<XMLOutputArchive>(this),
|
||||||
|
itsStream(stream),
|
||||||
|
itsOutputType( outputType )
|
||||||
{
|
{
|
||||||
// rapidxml will delete all allocations when xml_document is cleared
|
// rapidxml will delete all allocations when xml_document is cleared
|
||||||
auto node = itsXML.allocate_node( rapidxml::node_declaration );
|
auto node = itsXML.allocate_node( rapidxml::node_declaration );
|
||||||
@@ -97,20 +83,6 @@ namespace cereal
|
|||||||
itsXML.clear();
|
itsXML.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void createNode( std::string const & name )
|
|
||||||
{
|
|
||||||
createNode( name.c_str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void createNode( char const * name )
|
|
||||||
{
|
|
||||||
auto node = itsXML.allocate_node( rapidxml::node_element, name );
|
|
||||||
itsNodes.top().node->append_node( node );
|
|
||||||
itsNodes.emplace( node );
|
|
||||||
|
|
||||||
node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, "5432" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Saves some data, encoded as a string
|
//! Saves some data, encoded as a string
|
||||||
/*! The data will be be named with the most recent name if one exists,
|
/*! The data will be be named with the most recent name if one exists,
|
||||||
otherwise it will be given some default delimited value that depends upon
|
otherwise it will be given some default delimited value that depends upon
|
||||||
@@ -120,13 +92,9 @@ namespace cereal
|
|||||||
{
|
{
|
||||||
itsOS.clear(); itsOS.seekp(0);
|
itsOS.clear(); itsOS.seekp(0);
|
||||||
itsOS << value << std::ends;
|
itsOS << value << std::ends;
|
||||||
insertValueNode( itsOS.str().c_str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void insertValueNode( const char * data )
|
|
||||||
{
|
|
||||||
// allocate strings for all of the data in the XML object
|
// allocate strings for all of the data in the XML object
|
||||||
auto dataPtr = itsXML.allocate_string( data );
|
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str() );
|
||||||
|
|
||||||
// insert into the XML
|
// insert into the XML
|
||||||
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
|
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
|
||||||
@@ -151,6 +119,22 @@ namespace cereal
|
|||||||
itsNodes.emplace( node );
|
itsNodes.emplace( node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Causes the type to be appended to the most recently made node if output type is set to true
|
||||||
|
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.size() );
|
||||||
|
|
||||||
|
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) );
|
||||||
|
}
|
||||||
|
|
||||||
//! Designates the most recently added node as finished
|
//! Designates the most recently added node as finished
|
||||||
void finishNode()
|
void finishNode()
|
||||||
{
|
{
|
||||||
@@ -163,14 +147,22 @@ namespace cereal
|
|||||||
itsNodes.top().name = name;
|
itsNodes.top().name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Saves some binary data, encoded as a base64 string
|
//! Saves some binary data, encoded as a base64 string, with an optional name
|
||||||
void saveBinaryValue( const void * data, size_t size )
|
/*! This will create a new node, optionally named, and insert a value that consists of
|
||||||
|
the data encoded as a base64 string */
|
||||||
|
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 );
|
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
|
||||||
saveValue( base64string );
|
saveValue( base64string );
|
||||||
//auto decoded = base64::decode(base64string);
|
|
||||||
//int const * zz = (int const*)decoded.data();
|
if( itsOutputType )
|
||||||
//std::cout << zz[0] << " " << zz[1] << " " << zz[2] << std::endl;
|
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
|
||||||
|
|
||||||
|
finishNode();
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A struct that contains metadata about a node
|
//! A struct that contains metadata about a node
|
||||||
@@ -209,9 +201,41 @@ namespace cereal
|
|||||||
rapidxml::xml_document<> itsXML; //!< The XML document
|
rapidxml::xml_document<> itsXML; //!< The XML document
|
||||||
std::stack<NodeInfo> itsNodes; //!< A stack of nodes added to the document
|
std::stack<NodeInfo> itsNodes; //!< A stack of nodes added to the document
|
||||||
std::ostringstream itsOS; //!< Used to format strings internally
|
std::ostringstream itsOS; //!< Used to format strings internally
|
||||||
|
bool itsOutputType; //!< Controls whether type information is printed
|
||||||
}; // XMLOutputArchive
|
}; // XMLOutputArchive
|
||||||
|
|
||||||
struct XMLInputArchive;
|
// ######################################################################
|
||||||
|
//! An output archive designed to save data to XML
|
||||||
|
class XMLInputArchive : public InputArchive<XMLInputArchive>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Construct, reading in from the provided stream
|
||||||
|
/*! Reads in an entire XML document from some stream and parses it as soon
|
||||||
|
as serialization starts
|
||||||
|
|
||||||
|
@param stream The stream to read from. Can be a stringstream or a file. */
|
||||||
|
XMLInputArchive( std::istream & stream ) :
|
||||||
|
InputArchive<XMLInputArchive>( this ),
|
||||||
|
itsStream( stream ),
|
||||||
|
itsData( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
itsXML.parse<rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
|
||||||
|
}
|
||||||
|
catch( rapidxml::parse_error const & e )
|
||||||
|
{
|
||||||
|
throw Exception("XML Parsing failed - likely due to invalid characters or invalid naming");
|
||||||
|
//std::cout << e.what() << std::endl;
|
||||||
|
//std::cout << e.where<char>() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//private:
|
||||||
|
std::istream & itsStream;
|
||||||
|
std::vector<uint8_t> itsData; //!< The raw data loaded
|
||||||
|
rapidxml::xml_document<> itsXML; //!< The XML document
|
||||||
|
};
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
// XMLArchive prologue and epilogue functions
|
// XMLArchive prologue and epilogue functions
|
||||||
@@ -247,6 +271,7 @@ namespace cereal
|
|||||||
void prologue( XMLOutputArchive & ar, T const & data )
|
void prologue( XMLOutputArchive & ar, T const & data )
|
||||||
{
|
{
|
||||||
ar.startNode();
|
ar.startNode();
|
||||||
|
ar.insertType<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Epilogue for all other types other for XML archives
|
//! Epilogue for all other types other for XML archives
|
||||||
|
|||||||
244
include/cereal/external/rapidxml/rapidxml_utils.hpp
vendored
244
include/cereal/external/rapidxml/rapidxml_utils.hpp
vendored
@@ -1,122 +1,122 @@
|
|||||||
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
|
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
|
||||||
#define RAPIDXML_UTILS_HPP_INCLUDED
|
#define RAPIDXML_UTILS_HPP_INCLUDED
|
||||||
|
|
||||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||||
// Version 1.13
|
// Version 1.13
|
||||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||||
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
|
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
|
||||||
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
|
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
|
||||||
|
|
||||||
#include "rapidxml.hpp"
|
#include "rapidxml.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace rapidxml
|
namespace rapidxml
|
||||||
{
|
{
|
||||||
|
|
||||||
//! Represents data loaded from a file
|
//! Represents data loaded from a file
|
||||||
template<class Ch = char>
|
template<class Ch = char>
|
||||||
class file
|
class file
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
|
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
|
||||||
//! \param filename Filename to load.
|
//! \param filename Filename to load.
|
||||||
file(const char *filename)
|
file(const char *filename)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Open stream
|
// Open stream
|
||||||
basic_ifstream<Ch> stream(filename, ios::binary);
|
basic_ifstream<Ch> stream(filename, ios::binary);
|
||||||
if (!stream)
|
if (!stream)
|
||||||
throw runtime_error(string("cannot open file ") + filename);
|
throw runtime_error(string("cannot open file ") + filename);
|
||||||
stream.unsetf(ios::skipws);
|
stream.unsetf(ios::skipws);
|
||||||
|
|
||||||
// Determine stream size
|
// Determine stream size
|
||||||
stream.seekg(0, ios::end);
|
stream.seekg(0, ios::end);
|
||||||
size_t size = stream.tellg();
|
size_t size = stream.tellg();
|
||||||
stream.seekg(0);
|
stream.seekg(0);
|
||||||
|
|
||||||
// Load data and add terminating 0
|
// Load data and add terminating 0
|
||||||
m_data.resize(size + 1);
|
m_data.resize(size + 1);
|
||||||
stream.read(&m_data.front(), static_cast<streamsize>(size));
|
stream.read(&m_data.front(), static_cast<streamsize>(size));
|
||||||
m_data[size] = 0;
|
m_data[size] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor
|
//! Loads file into the memory. Data will be automatically destroyed by the destructor
|
||||||
//! \param stream Stream to load from
|
//! \param stream Stream to load from
|
||||||
file(std::basic_istream<Ch> &stream)
|
file(std::basic_istream<Ch> &stream)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Load data and add terminating 0
|
// Load data and add terminating 0
|
||||||
stream.unsetf(ios::skipws);
|
stream.unsetf(ios::skipws);
|
||||||
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
|
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
|
||||||
if (stream.fail() || stream.bad())
|
if (stream.fail() || stream.bad())
|
||||||
throw runtime_error("error reading stream");
|
throw runtime_error("error reading stream");
|
||||||
m_data.push_back(0);
|
m_data.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets file data.
|
//! Gets file data.
|
||||||
//! \return Pointer to data of file.
|
//! \return Pointer to data of file.
|
||||||
Ch *data()
|
Ch *data()
|
||||||
{
|
{
|
||||||
return &m_data.front();
|
return &m_data.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets file data.
|
//! Gets file data.
|
||||||
//! \return Pointer to data of file.
|
//! \return Pointer to data of file.
|
||||||
const Ch *data() const
|
const Ch *data() const
|
||||||
{
|
{
|
||||||
return &m_data.front();
|
return &m_data.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets file data size.
|
//! Gets file data size.
|
||||||
//! \return Size of file data, in characters.
|
//! \return Size of file data, in characters.
|
||||||
std::size_t size() const
|
std::size_t size() const
|
||||||
{
|
{
|
||||||
return m_data.size();
|
return m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<Ch> m_data; // File data
|
std::vector<Ch> m_data; // File data
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Counts children of node. Time complexity is O(n).
|
//! Counts children of node. Time complexity is O(n).
|
||||||
//! \return Number of children of node
|
//! \return Number of children of node
|
||||||
template<class Ch>
|
template<class Ch>
|
||||||
inline std::size_t count_children(xml_node<Ch> *node)
|
inline std::size_t count_children(xml_node<Ch> *node)
|
||||||
{
|
{
|
||||||
xml_node<Ch> *child = node->first_node();
|
xml_node<Ch> *child = node->first_node();
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
while (child)
|
while (child)
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
child = child->next_sibling();
|
child = child->next_sibling();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Counts attributes of node. Time complexity is O(n).
|
//! Counts attributes of node. Time complexity is O(n).
|
||||||
//! \return Number of attributes of node
|
//! \return Number of attributes of node
|
||||||
template<class Ch>
|
template<class Ch>
|
||||||
inline std::size_t count_attributes(xml_node<Ch> *node)
|
inline std::size_t count_attributes(xml_node<Ch> *node)
|
||||||
{
|
{
|
||||||
xml_attribute<Ch> *attr = node->first_attribute();
|
xml_attribute<Ch> *attr = node->first_attribute();
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
while (attr)
|
while (attr)
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
attr = attr->next_attribute();
|
attr = attr->next_attribute();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
sandbox.cpp
19
sandbox.cpp
@@ -299,7 +299,8 @@ int main()
|
|||||||
|
|
||||||
{
|
{
|
||||||
//std::stringstream os;
|
//std::stringstream os;
|
||||||
cereal::XMLOutputArchive oar( std::cout );
|
std::ofstream os("out.xml");
|
||||||
|
cereal::XMLOutputArchive oar( os );
|
||||||
oar( cereal::make_nvp("hello", 5 ) );
|
oar( cereal::make_nvp("hello", 5 ) );
|
||||||
std::string bla("bla");
|
std::string bla("bla");
|
||||||
oar( bla );
|
oar( bla );
|
||||||
@@ -318,13 +319,23 @@ int main()
|
|||||||
"there",
|
"there",
|
||||||
"buddy"};
|
"buddy"};
|
||||||
|
|
||||||
|
std::vector<std::vector<std::string>> vec2 = {vec, vec, vec};
|
||||||
|
|
||||||
Everything e;
|
Everything e;
|
||||||
oar( cereal::make_nvp("EVERYTHING?!", e) );
|
oar( cereal::make_nvp("EVERYTHING", e) );
|
||||||
oar( vec );
|
oar( vec );
|
||||||
//int xxx[] = {-1, 95, 3};
|
oar( vec2 );
|
||||||
//oar.saveBinaryValue( xxx, sizeof(int)*3);
|
|
||||||
|
int xxx[] = {-1, 95, 3};
|
||||||
|
oar.saveBinaryValue( xxx, sizeof(int)*3, "xxxbinary" );
|
||||||
|
oar.saveBinaryValue( xxx, sizeof(int)*3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ifstream is("out.xml");
|
||||||
|
cereal::XMLInputArchive oar( is );
|
||||||
|
std::cout << oar.itsData.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user