| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 | #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP#define BOOST_ARCHIVE_OSERIALIZER_HPP// MS compatible compilers support #pragma once#if defined(_MSC_VER)# pragma once#pragma inline_depth(511)#pragma inline_recursion(on)#endif#if defined(__MWERKS__)#pragma inline_depth(511)#endif/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8// oserializer.hpp: interface for serialization system.// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .// 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 <boost/assert.hpp>#include <cstddef> // NULL#include <boost/config.hpp>#include <boost/static_assert.hpp>#include <boost/detail/workaround.hpp>#include <boost/mpl/eval_if.hpp>#include <boost/mpl/equal_to.hpp>#include <boost/mpl/greater_equal.hpp>#include <boost/mpl/identity.hpp>#include <boost/mpl/bool_fwd.hpp>#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO    #include <boost/serialization/extended_type_info_typeid.hpp>#endif#include <boost/serialization/throw_exception.hpp>#include <boost/serialization/smart_cast.hpp>#include <boost/serialization/assume_abstract.hpp>#include <boost/serialization/static_warning.hpp>#include <boost/type_traits/is_pointer.hpp>#include <boost/type_traits/is_enum.hpp>#include <boost/type_traits/is_const.hpp>#include <boost/type_traits/is_polymorphic.hpp>#include <boost/type_traits/remove_extent.hpp>#include <boost/serialization/serialization.hpp>#include <boost/serialization/version.hpp>#include <boost/serialization/level.hpp>#include <boost/serialization/tracking.hpp>#include <boost/serialization/type_info_implementation.hpp>#include <boost/serialization/nvp.hpp>#include <boost/serialization/void_cast.hpp>#include <boost/serialization/collection_size_type.hpp>#include <boost/serialization/array_wrapper.hpp>#include <boost/serialization/singleton.hpp>#include <boost/archive/archive_exception.hpp>#include <boost/archive/detail/basic_oarchive.hpp>#include <boost/archive/detail/basic_oserializer.hpp>#include <boost/archive/detail/basic_pointer_oserializer.hpp>#include <boost/archive/detail/archive_serializer_map.hpp>#include <boost/archive/detail/check.hpp>#include <boost/core/addressof.hpp>namespace boost {namespace serialization {    class extended_type_info;} // namespace serializationnamespace archive {// an accessor to permit friend access to archives.  Needed because// some compilers don't handle friend templates completelyclass save_access {public:    template<class Archive>    static void end_preamble(Archive & ar){        ar.end_preamble();    }    template<class Archive, class T>    static void save_primitive(Archive & ar, const  T & t){        ar.end_preamble();        ar.save(t);    }};namespace detail {#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable : 4511 4512)#endiftemplate<class Archive, class T>class oserializer : public basic_oserializer{private:    // private constructor to inhibit any existence other than the    // static onepublic:    explicit BOOST_DLLEXPORT oserializer() :        basic_oserializer(            boost::serialization::singleton<                typename                boost::serialization::type_info_implementation< T >::type            >::get_const_instance()        )    {}    virtual BOOST_DLLEXPORT void save_object_data(        basic_oarchive & ar,        const void *x    ) const BOOST_USED;    virtual bool class_info() const {        return boost::serialization::implementation_level< T >::value            >= boost::serialization::object_class_info;    }    virtual bool tracking(const unsigned int /* flags */) const {        return boost::serialization::tracking_level< T >::value == boost::serialization::track_always            || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively                && serialized_as_pointer());    }    virtual version_type version() const {        return version_type(::boost::serialization::version< T >::value);    }    virtual bool is_polymorphic() const {        return boost::is_polymorphic< T >::value;    }    virtual ~oserializer(){}};#ifdef BOOST_MSVC#  pragma warning(pop)#endiftemplate<class Archive, class T>BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(    basic_oarchive & ar,    const void *x) const {    // make sure call is routed through the highest interface that might    // be specialized by the user.    BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);    boost::serialization::serialize_adl(        boost::serialization::smart_cast_reference<Archive &>(ar),        * static_cast<T *>(const_cast<void *>(x)),        version()    );}#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable : 4511 4512)#endiftemplate<class Archive, class T>class pointer_oserializer :    public basic_pointer_oserializer{private:    const basic_oserializer &    get_basic_serializer() const {        return boost::serialization::singleton<            oserializer<Archive, T>        >::get_const_instance();    }    virtual BOOST_DLLEXPORT void save_object_ptr(        basic_oarchive & ar,        const void * x    ) const BOOST_USED;public:    pointer_oserializer();    ~pointer_oserializer();};#ifdef BOOST_MSVC#  pragma warning(pop)#endiftemplate<class Archive, class T>BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(    basic_oarchive & ar,    const void * x) const {    BOOST_ASSERT(NULL != x);    // make sure call is routed through the highest interface that might    // be specialized by the user.    T * t = static_cast<T *>(const_cast<void *>(x));    const unsigned int file_version = boost::serialization::version< T >::value;    Archive & ar_impl        = boost::serialization::smart_cast_reference<Archive &>(ar);    boost::serialization::save_construct_data_adl<Archive, T>(        ar_impl,        t,        file_version    );    ar_impl << boost::serialization::make_nvp(NULL, * t);}template<class Archive, class T>pointer_oserializer<Archive, T>::pointer_oserializer() :    basic_pointer_oserializer(        boost::serialization::singleton<            typename            boost::serialization::type_info_implementation< T >::type        >::get_const_instance()    ){    // make sure appropriate member function is instantiated    boost::serialization::singleton<        oserializer<Archive, T>    >::get_mutable_instance().set_bpos(this);    archive_serializer_map<Archive>::insert(this);}template<class Archive, class T>pointer_oserializer<Archive, T>::~pointer_oserializer(){    archive_serializer_map<Archive>::erase(this);}template<class Archive>struct save_non_pointer_type {    // note this bounces the call right back to the archive    // with no runtime overhead    struct save_primitive {        template<class T>        static void invoke(Archive & ar, const T & t){            save_access::save_primitive(ar, t);        }    };    // same as above but passes through serialization    struct save_only {        template<class T>        static void invoke(Archive & ar, const T & t){            // make sure call is routed through the highest interface that might            // be specialized by the user.            boost::serialization::serialize_adl(                ar,                const_cast<T &>(t),                ::boost::serialization::version< T >::value            );        }    };    // adds class information to the archive. This includes    // serialization level and class version    struct save_standard {        template<class T>        static void invoke(Archive &ar, const T & t){            ar.save_object(                boost::addressof(t),                boost::serialization::singleton<                    oserializer<Archive, T>                >::get_const_instance()            );        }    };    // adds class information to the archive. This includes    // serialization level and class version    struct save_conditional {        template<class T>        static void invoke(Archive &ar, const T &t){            //if(0 == (ar.get_flags() & no_tracking))                save_standard::invoke(ar, t);            //else            //   save_only::invoke(ar, t);        }    };    template<class T>    static void invoke(Archive & ar, const T & t){        typedef            typename mpl::eval_if<            // if its primitive                mpl::equal_to<                    boost::serialization::implementation_level< T >,                    mpl::int_<boost::serialization::primitive_type>                >,                mpl::identity<save_primitive>,            // else            typename mpl::eval_if<                // class info / version                mpl::greater_equal<                    boost::serialization::implementation_level< T >,                    mpl::int_<boost::serialization::object_class_info>                >,                // do standard save                mpl::identity<save_standard>,            // else            typename mpl::eval_if<                    // no tracking                mpl::equal_to<                    boost::serialization::tracking_level< T >,                    mpl::int_<boost::serialization::track_never>                >,                // do a fast save                mpl::identity<save_only>,            // else                // do a fast save only tracking is turned off                mpl::identity<save_conditional>            > > >::type typex;        check_object_versioning< T >();        typex::invoke(ar, t);    }    template<class T>    static void invoke(Archive & ar, T & t){        check_object_level< T >();        check_object_tracking< T >();        invoke(ar, const_cast<const T &>(t));    }};template<class Archive>struct save_pointer_type {    struct abstract    {        template<class T>        static const basic_pointer_oserializer * register_type(Archive & /* ar */){            // it has? to be polymorphic            BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);            return NULL;        }    };    struct non_abstract    {        template<class T>        static const basic_pointer_oserializer * register_type(Archive & ar){            return ar.register_type(static_cast<T *>(NULL));        }    };    template<class T>    static const basic_pointer_oserializer * register_type(Archive &ar, T* const /*t*/){        // there should never be any need to save an abstract polymorphic        // class pointer.  Inhibiting code generation for this        // permits abstract base classes to be used - note: exception        // virtual serialize functions used for plug-ins        typedef            typename mpl::eval_if<                boost::serialization::is_abstract< T >,                mpl::identity<abstract>,                mpl::identity<non_abstract>            >::type typex;        return typex::template register_type< T >(ar);    }    struct non_polymorphic    {        template<class T>        static void save(            Archive &ar,            T & t        ){            const basic_pointer_oserializer & bpos =                boost::serialization::singleton<                    pointer_oserializer<Archive, T>                >::get_const_instance();            // save the requested pointer type            ar.save_pointer(& t, & bpos);        }    };    struct polymorphic    {        template<class T>        static void save(            Archive &ar,            T & t        ){            typename            boost::serialization::type_info_implementation< T >::type const            & i = boost::serialization::singleton<                typename                boost::serialization::type_info_implementation< T >::type            >::get_const_instance();            boost::serialization::extended_type_info const * const this_type = & i;            // retrieve the true type of the object pointed to            // if this assertion fails its an error in this library            BOOST_ASSERT(NULL != this_type);            const boost::serialization::extended_type_info * true_type =                i.get_derived_extended_type_info(t);            // note:if this exception is thrown, be sure that derived pointer            // is either registered or exported.            if(NULL == true_type){                boost::serialization::throw_exception(                    archive_exception(                        archive_exception::unregistered_class,                        "derived class not registered or exported"                    )                );            }            // if its not a pointer to a more derived type            const void *vp = static_cast<const void *>(&t);            if(*this_type == *true_type){                const basic_pointer_oserializer * bpos = register_type(ar, &t);                ar.save_pointer(vp, bpos);                return;            }            // convert pointer to more derived type. if this is thrown            // it means that the base/derived relationship hasn't be registered            vp = serialization::void_downcast(                *true_type,                *this_type,                static_cast<const void *>(&t)            );            if(NULL == vp){                boost::serialization::throw_exception(                    archive_exception(                        archive_exception::unregistered_cast,                        true_type->get_debug_info(),                        this_type->get_debug_info()                    )                );            }            // since true_type is valid, and this only gets made if the            // pointer oserializer object has been created, this should never            // fail            const basic_pointer_oserializer * bpos                = static_cast<const basic_pointer_oserializer *>(                    boost::serialization::singleton<                        archive_serializer_map<Archive>                    >::get_const_instance().find(*true_type)                );            BOOST_ASSERT(NULL != bpos);            if(NULL == bpos)                boost::serialization::throw_exception(                    archive_exception(                        archive_exception::unregistered_class,                        "derived class not registered or exported"                    )                );            ar.save_pointer(vp, bpos);        }    };    template<class T>    static void save(        Archive & ar,        const T & t    ){        check_pointer_level< T >();        check_pointer_tracking< T >();        typedef typename mpl::eval_if<            is_polymorphic< T >,            mpl::identity<polymorphic>,            mpl::identity<non_polymorphic>        >::type type;        type::save(ar, const_cast<T &>(t));    }    template<class TPtr>    static void invoke(Archive &ar, const TPtr t){        register_type(ar, t);        if(NULL == t){            basic_oarchive & boa                = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);            boa.save_null_pointer();            save_access::end_preamble(ar);            return;        }        save(ar, * t);    }};template<class Archive>struct save_enum_type{    template<class T>    static void invoke(Archive &ar, const T &t){        // convert enum to integers on save        const int i = static_cast<int>(t);        ar << boost::serialization::make_nvp(NULL, i);    }};template<class Archive>struct save_array_type{    template<class T>    static void invoke(Archive &ar, const T &t){        typedef typename boost::remove_extent< T >::type value_type;        save_access::end_preamble(ar);        // consider alignment        std::size_t c = sizeof(t) / (            static_cast<const char *>(static_cast<const void *>(&t[1]))            - static_cast<const char *>(static_cast<const void *>(&t[0]))        );        boost::serialization::collection_size_type count(c);        ar << BOOST_SERIALIZATION_NVP(count);        // explict template arguments to pass intel C++ compiler        ar << serialization::make_array<            const value_type,            boost::serialization::collection_size_type        >(            static_cast<const value_type *>(&t[0]),            count        );    }};} // detailtemplate<class Archive, class T>inline void save(Archive & ar, /*const*/ T &t){    typedef        typename mpl::eval_if<is_pointer< T >,            mpl::identity<detail::save_pointer_type<Archive> >,        //else        typename mpl::eval_if<is_enum< T >,            mpl::identity<detail::save_enum_type<Archive> >,        //else        typename mpl::eval_if<is_array< T >,            mpl::identity<detail::save_array_type<Archive> >,        //else            mpl::identity<detail::save_non_pointer_type<Archive> >        >        >        >::type typex;    typex::invoke(ar, t);}} // namespace archive} // namespace boost#endif // BOOST_ARCHIVE_OSERIALIZER_HPP
 |