diff --git a/CMake/CMakeLists.txt b/CMake/CMakeLists.txt index 1f07b529..c2471781 100644 --- a/CMake/CMakeLists.txt +++ b/CMake/CMakeLists.txt @@ -139,7 +139,6 @@ add_library(serialization ../src/extended_type_info.cpp ../src/polymorphic_iarchive.cpp ../src/polymorphic_oarchive.cpp - ../src/shared_ptr_helper.cpp ../src/stl_port.cpp ../src/text_iarchive.cpp ../src/text_oarchive.cpp @@ -220,7 +219,7 @@ function(polymorphic_archive_test test_name) add_executable(${amended_test_name} ../test/${test_name}.cpp ${arglist}) set_property( TARGET ${amended_test_name} - PROPERTY COMPILE_DEFINITIONS BOOST_ARCHIVE_TEST=${archive-name}.hpp + PROPERTY COMPILE_DEFINITIONS BOOST_ARCHIVE_TEST=polymorphic_${archive-name}.hpp ) target_link_libraries(${amended_test_name} serialization wserialization ${Boost_LIBRARIES}) add_test(${amended_test_name} ${amended_test_name}) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 8559b9d0..e3950a4c 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -80,7 +80,6 @@ SOURCES = xml_iarchive xml_oarchive xml_archive_exception - shared_ptr_helper ; WSOURCES = diff --git a/doc/archives.html b/doc/archives.html index cb5a5457..0dae69b4 100644 --- a/doc/archives.html +++ b/doc/archives.html @@ -182,6 +182,26 @@ equivalent to the original. The code that loads collections might be conditioned on the library version to make sure that libraries created by previous versions of the library can still be read. +

+ la.get_helper<Helper>() +
+ la.get_helper(u) +

+
+ The first time la.get_helper<Helper>() + is invoked for a given la with a particular copyable type + Helper, a default-constructed + Helper object is created, attached to + la and a reference to it is returned. Subsequent + invocations of la.get_helper<Helper>() return + a reference to the formerly constructed object. All objects created in this manner are + destroyed upon la destruction time. The purpose + of helper objects is discussed in + Special Considerations - Helper Support. + The second syntax is included to permit this function to be called on non-conforming + compilers when la is a template argument. + For more information, see Template Invocation syntax +

la.reset_object_address(v, u)

diff --git a/doc/contents.html b/doc/contents.html index 657c4a85..721abe0e 100644 --- a/doc/contents.html +++ b/doc/contents.html @@ -169,9 +169,6 @@ function initialize() {
pointer_tracking
const_loading - - -
Serialization Wrappers
@@ -188,6 +185,7 @@ function initialize() {
Object Tracking
Class Information +
Helper Support
Archive Portability
Numerics diff --git a/doc/implementation.html b/doc/implementation.html index 1caa390f..241d15eb 100644 --- a/doc/implementation.html +++ b/doc/implementation.html @@ -197,9 +197,18 @@ void register_type(T * t = NULL); so that one may write ar.register_type(static_cast<T *>(NULL)) instead of the syntax described above. +

+Similarly, the expression +


+ar.template get_helper<Helper>();
+
+that recovers a helper object of type Helper might pose problems, +in which case the following alternative syntax can be used: +

+ar.get_helper(static_cast<Helper *>(NULL));
+

Specific Compiler/Library Issues

-

GCC 3.X, 4.X

  • GCC versions for Cygwin and MinGW fail to support wide character I/O. diff --git a/doc/special.html b/doc/special.html index ea95bf6d..0e2b1396 100644 --- a/doc/special.html +++ b/doc/special.html @@ -28,6 +28,7 @@ http://www.boost.org/LICENSE_1_0.txt)
    Object Tracking
    Class Information +
    Helper Support
    Archive Portability
    Numerics @@ -155,6 +156,65 @@ redundant save/load operations. BOOST_CLASS_TRACKING(my_virtual_base_class, boost::serialization::track_always) +

    Helper Support

    +Some types, specially those with complicated lifetime behavior or limited +access to their internal state, might need or benefit from elaborate serialization +algorithms. In these cases, it can be advantageous to have a helper object +associated to the current archive that can be used to store contextual +information relevant to the particular type serialization algorithm. + +
    
    +class complex_type
    +{
    +   ...
    +};
    +
    +BOOST_SERIALIZATION_SPLIT_FREE(complex_type)
    +
    +class complex_type_serialization_helper
    +{
    +  // maintain contextual information for complex_type
    +  // serialization algorithm
    +};
    +
    +namespace boost {
    +namespace serialization {
    +
    +template<class Archive>
    +void save(Archive & ar, const complex_type & x, unsigned int /* version */)
    +{
    +    complex_type_serialization_helper & hlp =
    +        ar.template get_helper<complex_type_serialization_helper>();
    +        
    +    // implement complex_type save algorithm with the aid of hlp
    +}
    +
    +template<class Archive>
    +void load(Archive & ar, complex_type & x, unsigned int /* version */)
    +{
    +    complex_type_serialization_helper & hlp =
    +        ar.template get_helper<complex_type_serialization_helper>();
    +        
    +    // implement complex_type load algorithm with the aid of hlp
    +}
    +
    +} // namespace serialization
    +} // namespace boost
    +
    +get_helper<complex_type_serialization_helper>(); +creates a helper object associated to the archive the first time it is invoked; +subsequent invocations return a reference to the object created in the first +place, so that hlp can effectively be +used to store contextual information persisting through the serialization +of different complex_type objects on +the same archive. +Although the example code does not show it, the helper types used for saving and loading +can be different. A notable example of a type whose serialization routines use helper support +is boost::shared_ptr. The test +program test_helper_support.cpp +shows how to use helper support to implement a serialization algorithm +for a string type that avoids emitting duplicate contents. +

    Class Information

    By default, for each class serialized, class information is written to the archive. This information includes version number, implementation level and tracking diff --git a/include/boost/archive/basic_streambuf_locale_saver.hpp b/include/boost/archive/basic_streambuf_locale_saver.hpp index afb13f98..6bf8f715 100644 --- a/include/boost/archive/basic_streambuf_locale_saver.hpp +++ b/include/boost/archive/basic_streambuf_locale_saver.hpp @@ -50,7 +50,7 @@ public: explicit basic_streambuf_locale_saver( state_type &s ) : s_save_( s ), a_save_( s.getloc() ) {} - basic_streambuf_locale_saver( state_type &s, aspect_type const &a ) + explicit basic_streambuf_locale_saver( state_type &s, aspect_type const &a ) : s_save_( s ), a_save_( s.pubimbue(a) ) {} ~basic_streambuf_locale_saver() diff --git a/include/boost/archive/binary_iarchive.hpp b/include/boost/archive/binary_iarchive.hpp index a0b21cc5..d07bbbe4 100644 --- a/include/boost/archive/binary_iarchive.hpp +++ b/include/boost/archive/binary_iarchive.hpp @@ -56,13 +56,7 @@ public: } // namespace archive } // namespace boost -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - -namespace boost { +namespace boost { namespace archive { // do not derive from this class. If you want to extend this functionality @@ -73,9 +67,7 @@ class binary_iarchive : boost::archive::binary_iarchive, std::istream::char_type, std::istream::traits_type - >, - public detail::shared_ptr_helper -{ + >{ public: binary_iarchive(std::istream & is, unsigned int flags = 0) : binary_iarchive_impl< diff --git a/include/boost/archive/binary_wiarchive.hpp b/include/boost/archive/binary_wiarchive.hpp index fb183417..ce6576ee 100644 --- a/include/boost/archive/binary_wiarchive.hpp +++ b/include/boost/archive/binary_wiarchive.hpp @@ -56,12 +56,6 @@ public: } // namespace archive } // namespace boost -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - namespace boost { namespace archive { diff --git a/include/boost/archive/detail/basic_iarchive.hpp b/include/boost/archive/detail/basic_iarchive.hpp index 865f0448..fdafbbf8 100644 --- a/include/boost/archive/detail/basic_iarchive.hpp +++ b/include/boost/archive/detail/basic_iarchive.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include // must be the last header namespace boost { @@ -41,7 +42,8 @@ class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; ////////////////////////////////////////////////////////////////////// // class basic_iarchive - read serialized objects from a input stream class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive : - private boost::noncopyable + private boost::noncopyable, + public boost::archive::detail::helper_collection { friend class basic_iarchive_impl; // hide implementation of this class to minimize header conclusion diff --git a/include/boost/archive/detail/basic_oarchive.hpp b/include/boost/archive/detail/basic_oarchive.hpp index 73cd7980..f65d1103 100644 --- a/include/boost/archive/detail/basic_oarchive.hpp +++ b/include/boost/archive/detail/basic_oarchive.hpp @@ -25,7 +25,7 @@ #include #include - +#include #include // must be the last header namespace boost { @@ -39,10 +39,12 @@ namespace detail { class basic_oarchive_impl; class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + ////////////////////////////////////////////////////////////////////// // class basic_oarchive - write serialized objects to an output stream class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive : - private boost::noncopyable + private boost::noncopyable, + public boost::archive::detail::helper_collection { friend class basic_oarchive_impl; // hide implementation of this class to minimize header conclusion diff --git a/include/boost/archive/impl/xml_woarchive_impl.ipp b/include/boost/archive/impl/xml_woarchive_impl.ipp index 11b9a8dd..ff97daa5 100644 --- a/include/boost/archive/impl/xml_woarchive_impl.ipp +++ b/include/boost/archive/impl/xml_woarchive_impl.ipp @@ -135,20 +135,21 @@ xml_woarchive_impl::xml_woarchive_impl( // a) before output is invoked or // b) after flush has been called. This prevents one-to-many // transforms (such as one to many transforms from getting - // mixed up. Unfortunately, STLPort doesn't respect b) above - // so the restoration of the original archive locale done by - // the locale_saver doesn't get processed, - // before the current one is destroyed. - // so the codecvt doesn't get replaced with the orginal - // so closing the stream invokes codecvt::do_unshift - // so it crashes because the corresponding locale that contained - // the codecvt isn't around any more. - // we can hack around this by using a static codecvt that never - // gets destroyed. + // mixed up. if(0 == (flags & no_codecvt)){ boost::archive::detail::utf8_codecvt_facet *pfacet; #if defined(__SGI_STL_PORT) - static boost::archive::detail::utf8_codecvt_facet + // Unfortunately, STLPort doesn't respect b) above + // so the restoration of the original archive locale done by + // the locale_saver doesn't get processed, + // before the current one is destroyed. + // so the codecvt doesn't get replaced with the orginal + // so closing the stream invokes codecvt::do_unshift + // so it crashes because the corresponding locale that contained + // the codecvt isn't around any more. + // we can hack around this by using a static codecvt that never + // gets destroyed. + static boost::archive::detail::utf8_codecvt_facet facet(static_cast(1)); pfacet = & facet; #else diff --git a/include/boost/archive/polymorphic_iarchive.hpp b/include/boost/archive/polymorphic_iarchive.hpp index b32a2f03..4714dd31 100644 --- a/include/boost/archive/polymorphic_iarchive.hpp +++ b/include/boost/archive/polymorphic_iarchive.hpp @@ -155,18 +155,11 @@ public: #include // pops abi_suffix.hpp pragmas -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - -namespace boost { +namespace boost { namespace archive { class polymorphic_iarchive : - public polymorphic_iarchive_impl, - public detail::shared_ptr_helper + public polymorphic_iarchive_impl { public: virtual ~polymorphic_iarchive(){}; diff --git a/include/boost/archive/shared_ptr_helper.hpp b/include/boost/archive/shared_ptr_helper.hpp deleted file mode 100644 index 3df46055..00000000 --- a/include/boost/archive/shared_ptr_helper.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP -#define BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP - -// MS compatible compilers support #pragma once -#if defined(_MSC_VER) -# pragma once -#endif - -/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 -// shared_ptr_helper.hpp: serialization for boost shared pointern - -// (C) Copyright 2004-2009 Robert Ramey, Martin Ecker and Takatoshi Kondo -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org for updates, documentation, and revision history. - -#include -#include -#include -#include // NULL - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include // must be the last headern - -namespace boost_132 { - template class shared_ptr; -} -namespace boost { - template class shared_ptr; - namespace serialization { - class extended_type_info; - template - inline void load( - Archive & ar, - boost::shared_ptr< T > &t, - const unsigned int file_version - ); - } -namespace archive{ -namespace detail { - -/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 -// a common class for holding various types of shared pointers - -class shared_ptr_helper { - struct collection_type_compare { - bool operator()( - const shared_ptr &lhs, - const shared_ptr &rhs - )const{ - return lhs.get() < rhs.get(); - } - }; - typedef std::set< - boost::shared_ptr, - collection_type_compare - > collection_type; - typedef collection_type::const_iterator iterator_type; - // list of shared_pointers create accessable by raw pointer. This - // is used to "match up" shared pointers loaded at different - // points in the archive. Note, we delay construction until - // it is actually used since this is by default included as - // a "mix-in" even if shared_ptr isn't used. - collection_type * m_pointers; - - struct null_deleter { - void operator()(void const *) const {} - }; - - struct void_deleter { - const boost::serialization::extended_type_info * m_eti; - void_deleter(const boost::serialization::extended_type_info *eti) : - m_eti(eti) - {} - void operator()(void *vp) const { - m_eti->destroy(vp); - } - }; - -#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS -public: -#else - template - friend inline void boost::serialization::load( - Archive & ar, - boost::shared_ptr< T > &t, - const unsigned int file_version - ); -#endif - -// #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP - // list of loaded pointers. This is used to be sure that the pointers - // stay around long enough to be "matched" with other pointers loaded - // by the same archive. These are created with a "null_deleter" so that - // when this list is destroyed - the underlaying raw pointers are not - // destroyed. This has to be done because the pointers are also held by - // new system which is disjoint from this set. This is implemented - // by a change in load_construct_data below. It makes this file suitable - // only for loading pointers into a 1.33 or later boost system. - std::list > * m_pointers_132; -// #endif - - // returns pointer to object and an indicator whether this is a - // new entry (true) or a previous one (false) - BOOST_ARCHIVE_DECL(shared_ptr) - get_od( - const void * od, - const boost::serialization::extended_type_info * true_type, - const boost::serialization::extended_type_info * this_type - ); - - BOOST_ARCHIVE_DECL(void) - append(const boost::shared_ptr &); - - template - struct non_polymorphic { - static const boost::serialization::extended_type_info * - get_object_identifier(T &){ - return & boost::serialization::singleton< - BOOST_DEDUCED_TYPENAME - boost::serialization::type_info_implementation< T >::type - >::get_const_instance(); - } - }; - template - struct polymorphic { - static const boost::serialization::extended_type_info * - get_object_identifier(T & t){ - return boost::serialization::singleton< - BOOST_DEDUCED_TYPENAME - boost::serialization::type_info_implementation< T >::type - >::get_const_instance().get_derived_extended_type_info(t); - } - }; -public: - template - void reset(shared_ptr< T > & s, T * t){ - if(NULL == t){ - s.reset(); - return; - } - const boost::serialization::extended_type_info * this_type - = & boost::serialization::type_info_implementation< T >::type - ::get_const_instance(); - - // get pointer to the most derived object. This is effectively - // the object identifern - typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< - is_polymorphic< T >, - mpl::identity >, - mpl::identity > - >::type type; - - const boost::serialization::extended_type_info * true_type - = type::get_object_identifier(*t); - - // note:if this exception is thrown, be sure that derived pointern - // is either registered or exported. - if(NULL == true_type) - boost::serialization::throw_exception( - archive_exception( - archive_exception::unregistered_class, - this_type->get_debug_info() - ) - ); - shared_ptr r = - get_od( - static_cast(t), - true_type, - this_type - ); - if(!r){ - s.reset(t); - const void * od = void_downcast( - *true_type, - *this_type, - static_cast(t) - ); - shared_ptr sp(s, od); - append(sp); - } - else{ - s = shared_ptr< T >( - r, - static_cast(r.get()) - ); - } - } - -// #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP - BOOST_ARCHIVE_DECL(void) - append(const boost_132::shared_ptr & t); -// #endif -public: - BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) - shared_ptr_helper(); - BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) - ~shared_ptr_helper(); -}; - -} // namespace detail -} // namespace archive -} // namespace boost - -#include // pops abi_suffix.hpp pragmas - -#endif // BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP diff --git a/include/boost/archive/text_iarchive.hpp b/include/boost/archive/text_iarchive.hpp index fa0c88c8..13cb9930 100644 --- a/include/boost/archive/text_iarchive.hpp +++ b/include/boost/archive/text_iarchive.hpp @@ -121,12 +121,6 @@ public: #include // pops abi_suffix.hpp pragmas -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -136,9 +130,7 @@ namespace boost { namespace archive { class text_iarchive : - public text_iarchive_impl, - public detail::shared_ptr_helper -{ + public text_iarchive_impl{ public: text_iarchive(std::istream & is_, unsigned int flags = 0) : // note: added _ to suppress useless gcc warning diff --git a/include/boost/archive/text_wiarchive.hpp b/include/boost/archive/text_wiarchive.hpp index e386e490..b927a7e3 100644 --- a/include/boost/archive/text_wiarchive.hpp +++ b/include/boost/archive/text_wiarchive.hpp @@ -117,12 +117,6 @@ public: #include // pops abi_suffix.hpp pragmas -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -132,9 +126,7 @@ namespace boost { namespace archive { class text_wiarchive : - public text_wiarchive_impl, - public detail::shared_ptr_helper -{ + public text_wiarchive_impl{ public: text_wiarchive(std::wistream & is, unsigned int flags = 0) : text_wiarchive_impl(is, flags) diff --git a/include/boost/archive/xml_iarchive.hpp b/include/boost/archive/xml_iarchive.hpp index c82fe436..cdb8cdc3 100644 --- a/include/boost/archive/xml_iarchive.hpp +++ b/include/boost/archive/xml_iarchive.hpp @@ -129,13 +129,6 @@ public: #endif #include // pops abi_suffix.hpp pragmas - -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -145,9 +138,7 @@ namespace boost { namespace archive { class xml_iarchive : - public xml_iarchive_impl, - public detail::shared_ptr_helper -{ + public xml_iarchive_impl{ public: xml_iarchive(std::istream & is, unsigned int flags = 0) : xml_iarchive_impl(is, flags) diff --git a/include/boost/archive/xml_wiarchive.hpp b/include/boost/archive/xml_wiarchive.hpp index 253081fc..4d4e1a33 100644 --- a/include/boost/archive/xml_wiarchive.hpp +++ b/include/boost/archive/xml_wiarchive.hpp @@ -135,12 +135,6 @@ public: #include // pops abi_suffix.hpp pragmas -// note special treatment of shared_ptr. This type needs a special -// structure associated with every archive. We created a "mix-in" -// class to provide this functionality. Since shared_ptr holds a -// special esteem in the boost library - we included it here by default. -#include - #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -150,9 +144,7 @@ namespace boost { namespace archive { class xml_wiarchive : - public xml_wiarchive_impl, - public detail::shared_ptr_helper -{ + public xml_wiarchive_impl{ public: xml_wiarchive(std::wistream & is, unsigned int flags = 0) : xml_wiarchive_impl(is, flags) diff --git a/include/boost/serialization/shared_ptr.hpp b/include/boost/serialization/shared_ptr.hpp index d6d73c95..f348b12b 100644 --- a/include/boost/serialization/shared_ptr.hpp +++ b/include/boost/serialization/shared_ptr.hpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -130,13 +131,13 @@ inline void load( ar >> boost::serialization::make_nvp("px", sp.px); ar >> boost::serialization::make_nvp("pn", sp.pn); // got to keep the sps around so the sp.pns don't disappear - ar.append(sp); + ar.template get_helper().append(sp); r = sp.get(); } else{ ar >> boost::serialization::make_nvp("px", r); } - ar.reset(t,r); + ar.template get_helper().reset(t,r); } #else @@ -152,7 +153,7 @@ inline void load( BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never)); T* r; ar >> boost::serialization::make_nvp("px", r); - ar.reset(t,r); + ar.template get_helper().reset(t,r); } #endif diff --git a/src/basic_iarchive.cpp b/src/basic_iarchive.cpp index 87a44112..3a246900 100644 --- a/src/basic_iarchive.cpp +++ b/src/basic_iarchive.cpp @@ -418,7 +418,6 @@ basic_iarchive_impl::load_pointer( const basic_pointer_iserializer * (*finder)( const boost::serialization::extended_type_info & type_ ) - ){ m_moveable_objects.is_pointer = true; serialization::state_saver w(m_moveable_objects.is_pointer); @@ -452,7 +451,7 @@ basic_iarchive_impl::load_pointer( bpis_ptr = (*finder)(*eti); } BOOST_ASSERT(NULL != bpis_ptr); - class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); + // class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); BOOST_VERIFY(register_type(bpis_ptr->get_basic_serializer()) == cid); int i = cid; cobject_id_vector[i].bpis_ptr = bpis_ptr; diff --git a/src/shared_ptr_helper.cpp b/src/shared_ptr_helper.cpp deleted file mode 100644 index 0cb5f40e..00000000 --- a/src/shared_ptr_helper.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// MS compatible compilers support #pragma once -#if defined(_MSC_VER) -# pragma once -#endif - -/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 -// shared_ptr_helper.hpp: serialization for boost shared pointern - -// (C) Copyright 2004-2009 Robert Ramey, Martin Ecker and Takatoshi Kondo -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org for updates, documentation, and revision history. - -#include -#include -#include -#include // NULL - -#define BOOST_ARCHIVE_SOURCE -// include this to prevent linker errors when the -// same modules are marked export and import. -#define BOOST_SERIALIZATION_SOURCE - -#include -#include -#include -#include -#include - -namespace boost { -namespace archive{ -namespace detail { - -/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 -// a common class for holding various types of shared pointers - -// returns pointer to object and an indicator whether this is a -// new entry (true) or a previous one (false) -BOOST_ARCHIVE_DECL(shared_ptr) -shared_ptr_helper::get_od( - const void * t, - const boost::serialization::extended_type_info * true_type, - const boost::serialization::extended_type_info * this_type -){ - // get void pointer to the most derived type - // this uniquely identifies the object referred to - const void * od = void_downcast( - *true_type, - *this_type, - t - ); - if(NULL == od) - boost::serialization::throw_exception( - archive_exception( - archive_exception::unregistered_cast, - true_type->get_debug_info(), - this_type->get_debug_info() - ) - ); - - // make tracking array if necessary - if(NULL == m_pointers) - m_pointers = new collection_type; - - //shared_ptr sp(od, null_deleter()); - shared_ptr sp(od, null_deleter()); - collection_type::iterator i = m_pointers->find(sp); - - if(i == m_pointers->end()){ - shared_ptr np; - return np; - } - od = void_upcast( - *true_type, - *this_type, - i->get() - ); - if(NULL == od) - boost::serialization::throw_exception( - archive_exception( - archive_exception::unregistered_cast, - true_type->get_debug_info(), - this_type->get_debug_info() - ) - ); - - return shared_ptr( - const_pointer_cast(*i), - const_cast(od) - ); -} - -BOOST_ARCHIVE_DECL(void) -shared_ptr_helper::append(const boost::shared_ptr &sp){ - // make tracking array if necessary - if(NULL == m_pointers) - m_pointers = new collection_type; - - collection_type::iterator i = m_pointers->find(sp); - - if(i == m_pointers->end()){ - std::pair result; - result = m_pointers->insert(sp); - BOOST_ASSERT(result.second); - } -} - -// #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP -BOOST_ARCHIVE_DECL(void) -shared_ptr_helper::append(const boost_132::shared_ptr & t){ - if(NULL == m_pointers_132) - m_pointers_132 = new std::list >; - m_pointers_132->push_back(t); -} -// #endif -BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -shared_ptr_helper::shared_ptr_helper() : - m_pointers(NULL) - #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP - , m_pointers_132(NULL) - #endif -{} -BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -shared_ptr_helper::~shared_ptr_helper(){ - if(NULL != m_pointers) - delete m_pointers; - #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP - if(NULL != m_pointers_132) - delete m_pointers_132; - #endif -} - -} // namespace detail -} // namespace serialization -} // namespace boost - diff --git a/src/xml_archive_exception.cpp b/src/xml_archive_exception.cpp index d6289e0a..41d33fda 100644 --- a/src/xml_archive_exception.cpp +++ b/src/xml_archive_exception.cpp @@ -31,24 +31,23 @@ xml_archive_exception::xml_archive_exception( ) : archive_exception(other_exception, e1, e2) { - unsigned int length = 0; switch(c){ case xml_archive_parsing_error: - length = archive_exception::append(length, "unrecognized XML syntax"); + archive_exception::append(0, "unrecognized XML syntax"); break; case xml_archive_tag_mismatch: - length = archive_exception::append(length, "XML start/end tag mismatch"); + archive_exception::append(0, "XML start/end tag mismatch"); if(NULL != e1){ - length = archive_exception::append(length, " - "); - length = archive_exception::append(length, e1); + archive_exception::append(0, " - "); + archive_exception::append(0, e1); } break; case xml_archive_tag_name_error: - length = archive_exception::append(length, "Invalid XML tag name"); + archive_exception::append(0, "Invalid XML tag name"); break; default: BOOST_ASSERT(false); - length = archive_exception::append(length, "programming error"); + archive_exception::append(0, "programming error"); break; } } diff --git a/test/test_test_helper_support.cpp b/test/test_test_helper_support.cpp new file mode 100644 index 00000000..93376fe6 --- /dev/null +++ b/test/test_test_helper_support.cpp @@ -0,0 +1,129 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// test_helper_support.cpp + +// (C) Copyright 2008 Joaquin M Lopez Munoz. +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// should pass compilation and execution + +#include +#include +#include + +#include // remove +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::remove; +} +#endif + +#include "test_tools.hpp" +#include +#include +#include +#include +#include + +class my_string:public std::string +{ + typedef std::string super; + +public: + my_string(){} + my_string(const super & str): super(str){} + my_string & operator=(const super& str) + { + super::operator=(str); + return *this; + } + + const std::string& to_string() const { return *this; } +}; + +struct my_string_helper +{ + typedef std::vector table; + table t; +}; + +BOOST_SERIALIZATION_SPLIT_FREE(my_string) + +namespace boost { +namespace serialization { + +template +void save(Archive & ar, const my_string & str, unsigned int /* version */) +{ + typedef my_string_helper::table table; + table& t = ar.get_helper(static_cast(NULL)).t; + + table::iterator it = std::find(t.begin(), t.end(), str); + if(it == t.end()){ + table::size_type s = t.size(); + ar << make_nvp("index", s); + t.push_back(str); + ar << make_nvp("string", str.to_string()); + } + else{ + table::size_type s = (table::size_type)(it - t.begin()); + ar << make_nvp("index", s); + } +} + +template +void load(Archive & ar, my_string & str, unsigned int /* version */) +{ + typedef my_string_helper::table table; + table& t = ar.get_helper(static_cast(NULL)).t; + + table::size_type s = 0; + ar >> make_nvp("index", s); + if(s >= t.size()){ + std::string tmp; + ar>>make_nvp("string", tmp); + str = tmp; + t.push_back(str); + } + else{ + str = t[s]; + } +} + +} // namespace serialization +} // namespace boost + +int test_helper_support() +{ + const char * testfile = boost::archive::tmpnam(NULL); + BOOST_REQUIRE(NULL != testfile); + + std::vector v1; + for(int i=0; i<1000; ++i){ + v1.push_back(my_string(boost::lexical_cast(i % 100))); + } + const std::vector& cv1 = v1; + { + test_ostream os(testfile, TEST_STREAM_FLAGS); + test_oarchive oa(os, TEST_ARCHIVE_FLAGS); + oa << boost::serialization::make_nvp("vector", cv1); + } + { + std::vector v2; + test_istream is(testfile, TEST_STREAM_FLAGS); + test_iarchive ia(is, TEST_ARCHIVE_FLAGS); + ia >> boost::serialization::make_nvp("vector", v2); + BOOST_CHECK(cv1 == v2); + } + std::remove(testfile); + return EXIT_SUCCESS; +} + +int test_main( int /* argc */, char* /* argv */[] ) +{ + return test_helper_support(); +} + +// EOF