LCOV - code coverage report
Current view: top level - cereal/types - boost_variant.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 40 97.5 %
Date: 2022-01-16 21:05:07 Functions: 72 72 100.0 %

          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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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             : {
      46             :   namespace boost_variant_detail
      47             :   {
      48             :     //! @internal
      49             :     template <class Archive>
      50             :     struct variant_save_visitor : boost::static_visitor<>
      51             :     {
      52          16 :       variant_save_visitor(Archive & ar_) : ar(ar_) {}
      53             : 
      54             :       template<class T>
      55          16 :       void operator()(T const & value) const
      56             :       {
      57          16 :         ar( CEREAL_NVP_("data", value) );
      58          16 :       }
      59             : 
      60             :       Archive & ar;
      61             :     };
      62             : 
      63             :     //! @internal
      64             :     template <class Archive, class T>
      65             :     struct LoadAndConstructLoadWrapper
      66             :     {
      67             :       using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
      68             : 
      69           4 :       LoadAndConstructLoadWrapper() :
      70           4 :         construct( reinterpret_cast<T *>( &st ) )
      71           4 :       { }
      72             : 
      73           4 :       ~LoadAndConstructLoadWrapper()
      74             :       {
      75           4 :         if (construct.itsValid)
      76             :         {
      77           4 :           construct->~T();
      78             :         }
      79           4 :       }
      80             : 
      81           4 :       void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
      82             :       {
      83           4 :         ::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
      84           4 :       }
      85             : 
      86             :       ST st;
      87             :       ::cereal::construct<T> construct;
      88             :     };
      89             : 
      90             :     //! @internal
      91             :     template <class T> struct load_variant_wrapper;
      92             : 
      93             :     //! Avoid serializing variant void_ type
      94             :     /*! @internal */
      95             :     template <>
      96             :     struct load_variant_wrapper<boost::detail::variant::void_>
      97             :     {
      98             :       template <class Variant, class Archive>
      99             :       static void load_variant( Archive &, Variant & )
     100             :       { }
     101             :     };
     102             : 
     103             :     //! @internal
     104             :     template <class T>
     105             :     struct load_variant_wrapper
     106             :     {
     107             :       // default constructible
     108             :       template <class Archive, class Variant>
     109          12 :       static void load_variant_impl( Archive & ar, Variant & variant, std::true_type )
     110             :       {
     111           8 :         T value;
     112          12 :         ar( CEREAL_NVP_("data", value) );
     113          12 :         variant = std::move(value);
     114          12 :       }
     115             : 
     116             :       // not default constructible
     117             :       template<class Variant, class Archive>
     118           4 :       static void load_variant_impl(Archive & ar, Variant & variant, std::false_type )
     119             :       {
     120           8 :         LoadAndConstructLoadWrapper<Archive, T> loadWrapper;
     121             : 
     122           4 :         ar( CEREAL_NVP_("data", loadWrapper) );
     123           4 :         variant = std::move(*loadWrapper.construct.ptr());
     124           4 :       }
     125             : 
     126             :       //! @internal
     127             :       template<class Variant, class Archive>
     128          16 :       static void load_variant(Archive & ar, Variant & variant)
     129             :       {
     130          16 :         load_variant_impl( ar, variant, typename std::is_default_constructible<T>::type() );
     131          16 :       }
     132             :     };
     133             :   } // namespace boost_variant_detail
     134             : 
     135             :   //! Saving for boost::variant
     136             :   template <class Archive, typename ... VariantTypes> inline
     137          16 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
     138             :   {
     139          16 :     int32_t which = variant.which();
     140          16 :     ar( CEREAL_NVP_("which", which) );
     141          16 :     boost_variant_detail::variant_save_visitor<Archive> visitor(ar);
     142          16 :     variant.apply_visitor(visitor);
     143          16 :   }
     144             : 
     145             :   //! Loading for boost::variant
     146             :   template <class Archive, typename ... VariantTypes> inline
     147          16 :   void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
     148             :   {
     149             :     int32_t which;
     150          16 :     ar( CEREAL_NVP_("which", which) );
     151             : 
     152             :     using LoadFuncType = void(*)(Archive &, boost::variant<VariantTypes...> &);
     153          16 :     CEREAL_CONSTEXPR_LAMBDA LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant_wrapper<VariantTypes>::load_variant...};
     154             : 
     155          16 :     if(which >= int32_t(sizeof(loadFuncArray)/sizeof(loadFuncArray[0])))
     156           0 :       throw Exception("Invalid 'which' selector when deserializing boost::variant");
     157             : 
     158          16 :     loadFuncArray[which](ar, variant);
     159          16 :   }
     160             : } // namespace cereal
     161             : 
     162             : #undef CEREAL_CONSTEXPR_LAMBDA
     163             : 
     164             : #endif // CEREAL_TYPES_BOOST_VARIANT_HPP_

Generated by: LCOV version 1.14