adding size_tag wrappers, XML output looking good

This commit is contained in:
Shane Grant 2013-07-03 11:17:47 -07:00
parent d3ccaee633
commit 002b1ceeb1
20 changed files with 146 additions and 78 deletions

View File

@ -111,7 +111,7 @@ namespace cereal
ar( t.value );
}
//! Serializing NVP types to binary
//! Serializing SizeTags to binary
template <class Archive, class T> inline
CEREAL_ARCHIVE_RESTRICT_SERIALIZE(BinaryInputArchive, BinaryOutputArchive)
serialize( Archive & ar, SizeTag<T> & t )

View File

@ -78,16 +78,16 @@ namespace cereal
node->append_attribute( itsXML.allocate_attribute( "encoding", "utf-8" ) );
itsXML.append_node( node );
// allocate root node
auto root = itsXML.allocate_node( rapidxml::node_element, "cereal" );
itsXML.append_node( root );
itsNodes.emplace( root );
// testing
// set attributes on the streams
itsStream << std::boolalpha;
itsStream.precision( precision );
itsOS << std::boolalpha;
itsOS.precision( precision );
//itsStream.setf( std::ios::floatfield, std::ios::fixed );
}
//! Destructor, flushes the XML
@ -132,8 +132,14 @@ namespace cereal
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
}
//! Creates a new node that is a child of the node at the top of the stack
/*! Nodes will be given a name that has either been pre-set by a name value pair,
or generated based upon a counter unique to the parent node.
The node will then be pushed onto the node stack. */
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
@ -145,11 +151,13 @@ namespace cereal
itsNodes.emplace( node );
}
//! Designates the most recently added node as finished
void finishNode()
{
itsNodes.pop();
}
//! Sets the name for the next node created with startNode
void setNextName( const char * name )
{
itsNodes.top().name = name;
@ -165,6 +173,7 @@ namespace cereal
//std::cout << zz[0] << " " << zz[1] << " " << zz[2] << std::endl;
};
//! A struct that contains metadata about a node
struct NodeInfo
{
NodeInfo( rapidxml::xml_node<> * n = nullptr,
@ -174,10 +183,14 @@ namespace cereal
name( nm )
{ }
rapidxml::xml_node<> * node;
size_t counter;
const char * name;
rapidxml::xml_node<> * node; //!< A pointer to this node
size_t counter; //!< The counter for naming child nodes
const char * name; //!< The name for the next child node
//! Gets the name for the next child node created from this node
/*! The name will be automatically generated using the counter if
a name has not been previously set. If a name has been previously
set, that name will be returned only once */
std::string getValueName()
{
if( name )
@ -187,21 +200,66 @@ namespace cereal
return {n};
}
else
{
return "value" + std::to_string( counter++ ) + "\0";
}
}
};
}; // NodeInfo
private:
std::ostream & itsStream;
rapidxml::xml_document<> itsXML; //!< The XML document
std::stack<NodeInfo> itsNodes;
std::ostringstream itsOS;
};
std::stack<NodeInfo> itsNodes; //!< A stack of nodes added to the document
std::ostringstream itsOS; //!< Used to format strings internally
}; // XMLOutputArchive
struct XMLInputArchive;
// ######################################################################
// XMLArchive prologue and epilogue functions
//! Prologue for NVPs for XML archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T>
void prologue( XMLOutputArchive &, NameValuePair<T> const & )
{ }
//! Epilogue for NVPs for XML archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T>
void epilogue( XMLOutputArchive &, NameValuePair<T> const & )
{ }
//! Prologue for SizeTags for XML archives
/*! SizeTags are strictly ignored for XML */
template <class T>
void prologue( XMLOutputArchive &, SizeTag<T> const & )
{ }
//! Epilogue for SizeTags for XML archives
/*! SizeTags are strictly ignored for XML */
template <class T>
void epilogue( XMLOutputArchive &, SizeTag<T> const & )
{ }
//! Prologue for all other types for XML archives
/*! Starts a new node, named either automatically or by some NVP,
that may be given data by the type about to be archived */
template <class T>
void prologue( XMLOutputArchive & ar, T const & data )
{
ar.startNode();
}
//! Epilogue for all other types other for XML archives
/*! Finishes the node created in the prologue */
template <class T>
void epilogue( XMLOutputArchive & ar, T const & data )
{
ar.finishNode();
}
// ######################################################################
// Common XMLArchive serialization functions
//! Serializing NVP types to XML
template <class Archive, class T> inline
CEREAL_ARCHIVE_RESTRICT_SERIALIZE(XMLInputArchive, XMLOutputArchive)
@ -211,6 +269,12 @@ namespace cereal
ar( t.value );
}
//! Serializing SizeTags to XML
template <class Archive, class T> inline
CEREAL_ARCHIVE_RESTRICT_SERIALIZE(XMLInputArchive, XMLOutputArchive)
serialize( Archive & ar, SizeTag<T> & )
{ }
//! Saving for POD types to xml
template<class T> inline
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
@ -226,28 +290,6 @@ namespace cereal
ar.saveValue( str );
}
template <class T>
void prologue( XMLOutputArchive & ar, NameValuePair<T> const & data )
{ }
template <class T>
void epilogue( XMLOutputArchive & ar, NameValuePair<T> const & data )
{ }
template <class T>
void prologue( XMLOutputArchive & ar, T const & data )
{
ar.startNode();
}
template <class T>
void epilogue( XMLOutputArchive & ar, T const & data )
{
ar.finishNode();
}
// ######################################################################
// Common XMLArchive serialization functions
} // namespace cereal
// register archives for polymorphic support

View File

@ -49,6 +49,7 @@ namespace cereal
// ######################################################################
//! Creates a name value pair
/*! @relates NameValuePair */
template <class T> inline
NameValuePair<T> make_nvp( std::string const & name, T && value )
{
@ -56,6 +57,7 @@ namespace cereal
}
//! Creates a name value pair
/*! @relates NameValuePair */
template <class T> inline
NameValuePair<T> make_nvp( const char * name, T && value )
{
@ -63,18 +65,32 @@ namespace cereal
}
//! Creates a name value pair for the variable T with the same name as the variable
/*! @relates NameValuePair */
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
// ######################################################################
//! Convenience function to create binary data for both const and non const pointers
/*! @param data Pointer to beginning of the data
@param size The size in bytes of the data */
@param size The size in bytes of the data
@relates BinaryData */
template <class T> inline
BinaryData<T> binary_data( T && data, size_t size )
{
return {std::forward<T>(data), size};
}
// ######################################################################
//! Creates a size tag from some variable.
/*! Will normally be used to serialize size (e.g. size()) information for
containers.
@relates SizeTag */
template <class T>
SizeTag<T> make_size_tag( T && sz )
{
return {std::forward<T>(sz)};
}
// ######################################################################
//! Called before a type is serialized to set up any special archive state
//! for processing some type

View File

@ -27,6 +27,10 @@
#ifndef CEREAL_DETAILS_HELPERS_HPP_
#define CEREAL_DETAILS_HELPERS_HPP_
#include <type_traits>
#include <cstdint>
#include <utility>
namespace cereal
{
// ######################################################################
@ -103,6 +107,12 @@ namespace cereal
}
// ######################################################################
//! A wrapper around size metadata
/*! This class provides a way for archives to have more flexibility over how
they choose to serialize size metadata for containers. For some archive
types, the size may be implicitly encoded in the output (e.g. JSON) and
not need an explicit entry. Specializing serialize or load/save for
your archive and SizeTags allows you to choose what happens */
template <class T>
class SizeTag
{
@ -119,13 +129,6 @@ namespace cereal
Type size;
};
template <class T>
SizeTag<T> make_size_tag( T && sz )
{
return {std::forward<T>(sz)};
}
} // namespace cereal
#endif // CEREAL_DETAILS_HELPERS_HPP_

View File

@ -27,7 +27,6 @@
#ifndef CEREAL_TYPES_CHRONO_HPP_
#define CEREAL_TYPES_CHRONO_HPP_
#include <cereal/cereal.hpp>
#include <chrono>
namespace cereal

View File

@ -27,7 +27,7 @@
#ifndef CEREAL_TYPES_COMMON_HPP_
#define CEREAL_TYPES_COMMON_HPP_
#include <cereal/cereal.hpp>
#include <type_traits>
namespace cereal
{

View File

@ -27,7 +27,6 @@
#ifndef CEREAL_TYPES_COMPLEX_HPP_
#define CEREAL_TYPES_COMPLEX_HPP_
#include <cereal/cereal.hpp>
#include <complex>
namespace cereal

View File

@ -36,7 +36,7 @@ namespace cereal
template <class Archive, class T, class A> inline
void save( Archive & ar, std::deque<T, A> const & deque )
{
ar( deque.size() );
ar( make_size_tag( deque.size() ) );
for( auto const & i : deque )
ar( i );
@ -47,7 +47,7 @@ namespace cereal
void load( Archive & ar, std::deque<T, A> & deque )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
deque.resize( size );

View File

@ -41,7 +41,7 @@ namespace cereal
// since it works in the most general fashion with any archive type
const size_t size = std::distance( forward_list.begin(), forward_list.end() );
ar( size );
ar( make_size_tag( size ) );
// write the list
for( const auto & i : forward_list )
@ -53,7 +53,7 @@ namespace cereal
void load( Archive & ar, std::forward_list<T, A> & forward_list )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
forward_list.resize( size );

View File

@ -36,7 +36,7 @@ namespace cereal
template <class Archive, class T, class A> inline
void save( Archive & ar, std::list<T, A> const & list )
{
ar( list.size() );
ar( make_size_tag( list.size() ) );
for( auto const & i : list )
ar( i );
@ -47,7 +47,7 @@ namespace cereal
void load( Archive & ar, std::list<T, A> & list )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
list.resize( size );

View File

@ -27,8 +27,7 @@
#ifndef CEREAL_TYPES_MAP_HPP_
#define CEREAL_TYPES_MAP_HPP_
//#include <cereal/cereal.hpp>
#include <cereal/details/helpers.hpp>
#include <cereal/cereal.hpp>
#include <map>
namespace cereal
@ -38,7 +37,7 @@ namespace cereal
template <class Archive, class MapT> inline
void save( Archive & ar, MapT const & map )
{
ar( map.size() );
ar( make_size_tag( map.size() ) );
for( const auto & i : map )
ar( i.first, i.second );
@ -48,7 +47,7 @@ namespace cereal
void load( Archive & ar, MapT & map )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
map.clear();

View File

@ -29,9 +29,11 @@
#include <cereal/cereal.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/details/polymorphic_impl.hpp>
#include <cereal/details/util.hpp>
#include <cereal/details/helpers.hpp>
#include <cereal/details/traits.hpp>
#include <cereal/details/polymorphic_impl.hpp>
//! Registers a polymorphic type with cereal
/*! Polymorphic types must be registered before pointers
@ -145,7 +147,7 @@ namespace cereal
template<class Archive, class T, class D> inline
typename std::enable_if<!std::is_default_constructible<T>::value && !traits::has_load_and_allocate<T, Archive>(), bool>::type
serialize_wrapper(Archive & ar, std::unique_ptr<T, D> & ptr, std::uint32_t const nameid)
{
{
if(nameid & detail::msb2_32bit)
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_allocate function");
return false;
@ -199,7 +201,7 @@ namespace cereal
ar( nameid );
// Check to see if we can skip all of this polymorphism business
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
return;
auto binding = polymorphic_detail::getInputBinding(ar, nameid);
@ -271,7 +273,7 @@ namespace cereal
ar( nameid );
// Check to see if we can skip all of this polymorphism business
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
return;
auto binding = polymorphic_detail::getInputBinding(ar, nameid);

View File

@ -27,7 +27,7 @@
#ifndef CEREAL_TYPES_QUEUE_HPP_
#define CEREAL_TYPES_QUEUE_HPP_
#include <cereal/cereal.hpp>
#include <cereal/details/helpers.hpp>
#include <queue>
namespace cereal

View File

@ -37,7 +37,7 @@ namespace cereal
template <class Archive, class SetT> inline
void save( Archive & ar, SetT const & set )
{
ar( set.size() );
ar( make_size_tag( set.size() ) );
for( const auto & i : set )
ar( i );
@ -47,7 +47,7 @@ namespace cereal
void load( Archive & ar, SetT & set )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
set.clear();

View File

@ -27,8 +27,7 @@
#ifndef CEREAL_TYPES_STRING_HPP_
#define CEREAL_TYPES_STRING_HPP_
#include <cereal/details/helpers.hpp>
#include <cereal/details/traits.hpp>
#include <cereal/cereal.hpp>
#include <string>
namespace cereal
@ -40,7 +39,6 @@ namespace cereal
{
// Save number of chars + the data
ar( make_size_tag( str.size() ) );
//ar( str.size() );
ar( binary_data( str.data(), str.size() * sizeof(CharT) ) );
}

View File

@ -37,7 +37,7 @@ namespace cereal
template <class Archive, class MapT> inline
void save( Archive & ar, MapT const & map )
{
ar( map.size() );
ar( make_size_tag( map.size() ) );
for( const auto & i : map )
ar( i.first, i.second );
@ -47,7 +47,7 @@ namespace cereal
void load( Archive & ar, MapT & map )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
map.clear();
map.reserve( size );

View File

@ -37,7 +37,7 @@ namespace cereal
template <class Archive, class SetT> inline
void save( Archive & ar, SetT const & set )
{
ar( set.size() );
ar( make_size_tag( set.size() ) );
for( const auto & i : set )
ar( i );
@ -47,7 +47,7 @@ namespace cereal
void load( Archive & ar, SetT & set )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
set.clear();
set.reserve( size );

View File

@ -30,8 +30,6 @@
#include <cereal/cereal.hpp>
#include <vector>
#include <iostream>
namespace cereal
{
//! Serialization for std::vectors of arithmetic (but not bool) using binary serialization, if supported
@ -40,7 +38,7 @@ namespace cereal
&& std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type
save( Archive & ar, std::vector<T, A> const & vector )
{
ar( vector.size() ); // number of elements
ar( make_size_tag( vector.size() ) ); // number of elements
ar( binary_data( vector.data(), vector.size() * sizeof(T) ) );
}
@ -51,7 +49,7 @@ namespace cereal
load( Archive & ar, std::vector<T, A> & vector )
{
size_t vectorSize;
ar( vectorSize );
ar( make_size_tag( vectorSize ) );
vector.resize( vectorSize );
ar( binary_data( vector.data(), vectorSize * sizeof(T) ) );
@ -64,7 +62,7 @@ namespace cereal
|| std::is_same<T, bool>::value, void>::type
save( Archive & ar, std::vector<T, A> const & vector )
{
ar( vector.size() ); // number of elements
ar( make_size_tag( vector.size() ) ); // number of elements
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )
ar( *it );
}
@ -77,7 +75,7 @@ namespace cereal
load( Archive & ar, std::vector<T, A> & vector )
{
size_t size;
ar( size );
ar( make_size_tag( size ) );
vector.resize( size );
for( auto it = vector.begin(), end = vector.end(); it != end; ++it )

View File

@ -28,12 +28,14 @@
#include <cereal/cereal.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/utility.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/complex.hpp>
#include <cereal/types/boost_variant.hpp>
#include <cereal/types/base_class.hpp>
#include <cereal/types/array.hpp>
#include <cereal/types/vector.hpp>
#include <cxxabi.h>
#include <sstream>
@ -309,7 +311,16 @@ int main()
oar( 3.2f );
oar( true );
std::array<int,5> arr = {1, 2, 3, 4, 5};
std::array<int,5> arr = {{1, 2, 3, 4, 5}};
oar( arr );
std::vector<std::string> vec = {"hey",
"there",
"buddy"};
Everything e;
oar( cereal::make_nvp("EVERYTHING?!", e) );
oar( vec );
//int xxx[] = {-1, 95, 3};
//oar.saveBinaryValue( xxx, sizeof(int)*3);
}

View File

@ -24,7 +24,6 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cereal/archives/binary.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/array.hpp>
#include <cereal/types/vector.hpp>
@ -43,6 +42,8 @@
#include <cereal/types/bitset.hpp>
#include <cereal/types/complex.hpp>
#include <cereal/types/chrono.hpp>
#include <cereal/archives/binary.hpp>
#include <limits>
#include <random>