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