source: NonGTP/Boost/boost/serialization/variant.hpp @ 857

Revision 857, 4.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1#ifndef BOOST_SERIALIZATION_VARIANT_HPP
2#define BOOST_SERIALIZATION_VARIANT_HPP
3
4// MS compatible compilers support #pragma once
5#if defined(_MSC_VER) && (_MSC_VER >= 1020)
6# pragma once
7#endif
8
9#if defined(_MSC_VER) && (_MSC_VER <= 1020)
10#  pragma warning (disable : 4786) // too long name, harmless warning
11#endif
12
13/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
14// variant.hpp - non-intrusive serialization of variant types
15//
16// copyright (c) 2005   
17// troy d. straszheim <troy@resophonic.com>
18// http://www.resophonic.com
19//
20// Use, modification and distribution is subject to the Boost Software
21// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
22// http://www.boost.org/LICENSE_1_0.txt)
23//
24// See http://www.boost.org for updates, documentation, and revision history.
25//
26// thanks to Robert Ramey, Peter Dimov, and Richard Crossley.
27//
28
29#include <boost/mpl/front.hpp>
30#include <boost/mpl/pop_front.hpp>
31#include <boost/mpl/eval_if.hpp>
32#include <boost/mpl/identity.hpp>
33#include <boost/mpl/size.hpp>
34#include <boost/mpl/empty.hpp>
35
36#include <boost/throw_exception.hpp>
37
38#include <boost/variant.hpp>
39
40#include <boost/archive/archive_exception.hpp>
41
42#include <boost/serialization/split_free.hpp>
43#include <boost/serialization/serialization.hpp>
44
45namespace boost {
46namespace serialization {
47
48template<class Archive>
49struct variant_save_visitor : boost::static_visitor<> {
50    variant_save_visitor(Archive& ar) :
51        m_ar(ar)
52    {}
53    template<class T>
54    void operator()(T const & value) const
55    {
56        m_ar << BOOST_SERIALIZATION_NVP(value);
57    }
58private:
59    Archive & m_ar;
60};
61
62template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
63void save(
64    Archive & ar,
65    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const & v,
66    unsigned int version
67){
68    int which = v.which();
69    ar << BOOST_SERIALIZATION_NVP(which);
70    typedef BOOST_DEDUCED_TYPENAME  boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
71    variant_save_visitor<Archive> visitor(ar);
72    v.apply_visitor(visitor);
73}
74
75template<class S>
76struct variant_impl {
77
78    struct load_null {
79        template<class Archive, class V>
80        static void invoke(
81            Archive & ar,
82            int which,
83            V & v,
84            unsigned int version
85        ){}
86    };
87
88    struct load_impl {
89        template<class Archive, class V>
90        static void invoke(
91            Archive & ar,
92            int which,
93            V & v,
94            unsigned int version
95        ){
96            if(which == 0){
97                // note: A non-intrusive implementation (such as this one)
98                // necessary has to copy the value.  This wouldn't be necessary
99                // with an implementation that de-serialized to the address of the
100                // aligned storage included in the variant.
101                typedef BOOST_DEDUCED_TYPENAME mpl::front<S>::type head_type;
102                head_type value;
103                ar >> BOOST_SERIALIZATION_NVP(value);
104                v = value;
105                ar.reset_object_address(& boost::get<head_type>(v), & value);
106                return;
107            }
108            typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<S>::type type;
109            variant_impl<type>::load(ar, which - 1, v, version);
110        }
111    };
112
113    template<class Archive, class V>
114    static void load(
115        Archive & ar,
116        int which,
117        V & v,
118        unsigned int version
119    ){
120        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<mpl::empty<S>,
121            mpl::identity<load_null>,
122            mpl::identity<load_impl>
123        >::type typex;
124        typex::invoke(ar, which, v, version);
125    }
126
127};
128
129template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
130void load(
131    Archive & ar,
132    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v,
133    unsigned int version
134){
135    int which;
136    typedef BOOST_DEDUCED_TYPENAME boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
137    ar >> BOOST_SERIALIZATION_NVP(which);
138    if(which >=  mpl::size<types>::value)
139        // this might happen if a type was removed from the list of variant types
140        boost::throw_exception(
141            boost::archive::archive_exception(
142                boost::archive::archive_exception::unsupported_version
143            )
144        );
145    variant_impl<types>::load(ar, which, v, version);
146}
147
148template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
149inline void serialize(
150    Archive & ar,
151    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v,
152    unsigned int file_version
153){
154    split_free(ar,v,file_version);
155}
156
157} // namespace serialization
158} // namespace boost
159
160#endif //BOOST_SERIALIZATION_VARIANT_HPP
161
Note: See TracBrowser for help on using the repository browser.