LCOV - code coverage report
Current view: top level - cereal/types - boost_variant.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 360 371 97.0 %
Date: 2019-10-22 20:09:23 Functions: 92 96 95.8 %

          Line data    Source code
       1             : /*! \file boost_variant.hpp
       2             :     \brief Support for boost::variant
       3             :     \ingroup OtherTypes */
       4             : /*
       5             :   Copyright (c) 2014, Randolph Voorhies, Shane Grant
       6             :   All rights reserved.
       7             : 
       8             :   Redistribution and use in source and binary forms, with or without
       9             :   modification, are permitted provided that the following conditions are met:
      10             :       * Redistributions of source code must retain the above copyright
      11             :         notice, this list of conditions and the following disclaimer.
      12             :       * Redistributions in binary form must reproduce the above copyright
      13             :         notice, this list of conditions and the following disclaimer in the
      14             :         documentation and/or other materials provided with the distribution.
      15             :       * Neither the name of cereal nor the
      16             :         names of its contributors may be used to endorse or promote products
      17             :         derived from this software without specific prior written permission.
      18             : 
      19             :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
      20             :   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      21             :   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      22             :   DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
      23             :   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      24             :   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      25             :   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      26             :   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27             :   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      28             :   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29             : */
      30             : #ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_
      31             : #define CEREAL_TYPES_BOOST_VARIANT_HPP_
      32             : 
      33             : //! @internal
      34             : #if defined(_MSC_VER) && _MSC_VER < 1911
      35             : #define CEREAL_CONSTEXPR_LAMBDA
      36             : #else // MSVC 2017 or newer, all other compilers
      37             : #define CEREAL_CONSTEXPR_LAMBDA constexpr
      38             : #endif
      39             : 
      40             : #include "cereal/cereal.hpp"
      41             : #include <boost/variant/variant_fwd.hpp>
      42             : #include <boost/variant/static_visitor.hpp>
      43             : 
      44             : namespace cereal
      45          12 : {
      46             :   namespace boost_variant_detail
      47             :   {
      48          12 :     //! @internal
      49             :     template <class Archive>
      50          12 :     struct variant_save_visitor : boost::static_visitor<>
      51          12 :     {
      52          17 :       variant_save_visitor(Archive & ar_) : ar(ar_) {}
      53             : 
      54           1 :       template<class T>
      55          17 :       void operator()(T const & value) const
      56           1 :       {
      57          16 :         ar( CEREAL_NVP_("data", value) );
      58          17 :       }
      59           2 : 
      60           1 :       Archive & ar;
      61           1 :     };
      62           2 : 
      63           2 :     //! @internal
      64           1 :     template <class Archive, class T>
      65           1 :     struct LoadAndConstructLoadWrapper
      66           2 :     {
      67           2 :       using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
      68           1 : 
      69           1 :       LoadAndConstructLoadWrapper() :
      70           2 :         construct( reinterpret_cast<T *>( &st ) )
      71           2 :       { }
      72           1 : 
      73           1 :       ~LoadAndConstructLoadWrapper()
      74           2 :       {
      75           2 :         if (construct.itsValid)
      76           1 :         {
      77           1 :           construct->~T();
      78           2 :         }
      79           2 :       }
      80           1 : 
      81           1 :       void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
      82           2 :       {
      83           2 :         ::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
      84           1 :       }
      85           1 : 
      86           2 :       ST st;
      87           2 :       ::cereal::construct<T> construct;
      88           1 :     };
      89           1 : 
      90           2 :     //! @internal
      91           2 :     template <class T> struct load_variant_wrapper;
      92           1 : 
      93           1 :     //! Avoid serializing variant void_ type
      94           2 :     /*! @internal */
      95           2 :     template <>
      96           1 :     struct load_variant_wrapper<boost::detail::variant::void_>
      97           1 :     {
      98           2 :       template <class Variant, class Archive>
      99           2 :       static void load_variant( Archive &, Variant & )
     100             :       { }
     101           1 :     };
     102           1 : 
     103           1 :     //! @internal
     104             :     template <class T>
     105           1 :     struct load_variant_wrapper
     106           1 :     {
     107           1 :       // default constructible
     108             :       template <class Archive, class Variant>
     109           1 :       static void load_variant_impl( Archive & ar, Variant & variant, std::true_type )
     110           1 :       {
     111           1 :         T value;
     112             :         ar( CEREAL_NVP_("data", value) );
     113           1 :         variant = std::move(value);
     114           1 :       }
     115           1 : 
     116             :       // not default constructible
     117           1 :       template<class Variant, class Archive>
     118           1 :       static void load_variant_impl(Archive & ar, Variant & variant, std::false_type )
     119           1 :       {
     120             :         LoadAndConstructLoadWrapper<Archive, T> loadWrapper;
     121           1 : 
     122           1 :         ar( CEREAL_NVP_("data", loadWrapper) );
     123           0 :         variant = std::move(*loadWrapper.construct.ptr());
     124             :       }
     125           0 : 
     126             :       //! @internal
     127             :       template<class Variant, class Archive>
     128             :       static void load_variant(Archive & ar, Variant & variant)
     129             :       {
     130             :         load_variant_impl( ar, variant, typename std::is_default_constructible<T>::type() );
     131          24 :       }
     132             :     };
     133          28 :   } // namespace boost_variant_detail
     134           4 : 
     135          12 :   //! Saving for boost::variant
     136          13 :   template <class Archive, typename ... VariantTypes> inline
     137          13 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
     138           1 :   {
     139           1 :     int32_t which = variant.which();
     140          13 :     ar( CEREAL_NVP_("which", which) );
     141          25 :     boost_variant_detail::variant_save_visitor<Archive> visitor(ar);
     142           2 :     variant.apply_visitor(visitor);
     143           1 :   }
     144           2 : 
     145           1 :   //! Loading for boost::variant
     146           3 :   template <class Archive, typename ... VariantTypes> inline
     147           2 :   void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
     148           1 :   {
     149           4 :     int32_t which;
     150             :     ar( CEREAL_NVP_("which", which) );
     151           4 : 
     152           1 :     using LoadFuncType = void(*)(Archive &, boost::variant<VariantTypes...> &);
     153           5 :     CEREAL_CONSTEXPR_LAMBDA LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant_wrapper<VariantTypes>::load_variant...};
     154             : 
     155           5 :     if(which >= int32_t(sizeof(loadFuncArray)/sizeof(loadFuncArray[0])))
     156           1 :       throw Exception("Invalid 'which' selector when deserializing boost::variant");
     157           2 : 
     158           2 :     loadFuncArray[which](ar, variant);
     159           1 :   }
     160           1 : } // namespace cereal
     161             : 
     162           1 : #undef CEREAL_CONSTEXPR_LAMBDA
     163           2 : 
     164           1 : #endif // CEREAL_TYPES_BOOST_VARIANT_HPP_

Generated by: LCOV version 1.13