os/ossrv/ossrv_pub/boost_apis/boost/serialization/variant.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 
    45 namespace boost {
    46 namespace serialization {
    47 
    48 template<class Archive>
    49 struct 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     }
    58 private:
    59     Archive & m_ar;
    60 };
    61 
    62 template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
    63 void 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 
    75 template<class S>
    76 struct 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 
   129 template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
   130 void 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 
   148 template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
   149 inline 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