LCOV - code coverage report
Current view: top level - cereal/types - bitset.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 432 770 56.1 %
Date: 2019-10-22 20:09:23 Functions: 32 32 100.0 %

          Line data    Source code
       1             : /*! \file bitset.hpp
       2             :     \brief Support for types found in \<bitset\>
       3             :     \ingroup STLSupport */
       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_BITSET_HPP_
      31             : #define CEREAL_TYPES_BITSET_HPP_
      32             : 
      33             : #include "cereal/cereal.hpp"
      34             : #include "cereal/types/string.hpp"
      35             : #include <bitset>
      36             : 
      37             : namespace cereal
      38             : {
      39             :   namespace bitset_detail
      40             :   {
      41             :     //! The type the bitset is encoded with
      42             :     /*! @internal */
      43             :     enum class type : uint8_t
      44             :     {
      45             :       ulong,
      46             :       ullong,
      47             :       string,
      48             :       bits
      49             :     };
      50             :   }
      51             : 
      52             :   //! Serializing (save) for std::bitset when BinaryData optimization supported
      53             :   template <class Archive, size_t N,
      54             :             traits::EnableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
      55             :             = traits::sfinae> inline
      56        2000 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
      57             :   {
      58        2000 :     ar( CEREAL_NVP_("type", bitset_detail::type::bits) );
      59             : 
      60             :     // Serialize 8 bit chunks
      61        2000 :     std::uint8_t chunk = 0;
      62        2000 :     std::uint8_t mask = 0x80;
      63             : 
      64             :     // Set each chunk using a rotating mask for the current bit
      65      360800 :     for( std::size_t i = 0; i < N; ++i )
      66             :     {
      67      358800 :       if( bits[i] )
      68      172966 :         chunk |= mask;
      69             : 
      70      358800 :       mask = static_cast<std::uint8_t>(mask >> 1);
      71             : 
      72             :       // output current chunk when mask is empty (8 bits)
      73      358800 :       if( mask == 0 )
      74             :       {
      75       44800 :         ar( chunk );
      76       44800 :         chunk = 0;
      77       44800 :         mask = 0x80;
      78             :       }
      79             :     }
      80             : 
      81             :     // serialize remainder, if it exists
      82        2000 :     if( mask != 0x80 )
      83         400 :       ar( chunk );
      84        2000 :   }
      85         200 : 
      86             :   //! Serializing (save) for std::bitset when BinaryData is not supported
      87         200 :   template <class Archive, size_t N,
      88             :             traits::DisableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
      89             :             = traits::sfinae> inline
      90         200 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
      91         200 :   {
      92             :     try
      93             :     {
      94      102600 :       auto const b = bits.to_ulong();
      95             :       ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
      96      102400 :       ar( CEREAL_NVP_("data", b) );
      97       51161 :     }
      98             :     catch( std::overflow_error const & )
      99      102400 :     {
     100             :       try
     101             :       {
     102      102400 :         auto const b = bits.to_ullong();
     103             :         ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
     104       12800 :         ar( CEREAL_NVP_("data", b) );
     105       12800 :       }
     106       12800 :       catch( std::overflow_error const & )
     107             :       {
     108             :         ar( CEREAL_NVP_("type", bitset_detail::type::string) );
     109             :         ar( CEREAL_NVP_("data", bits.to_string()) );
     110             :       }
     111         200 :     }
     112           0 :   }
     113         200 : 
     114         200 :   //! Serializing (load) for std::bitset
     115             :   template <class Archive, size_t N> inline
     116         200 :   void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
     117             :   {
     118             :     bitset_detail::type t;
     119         200 :     ar( CEREAL_NVP_("type", t) );
     120         200 : 
     121             :     switch( t )
     122             :     {
     123       51400 :       case bitset_detail::type::ulong:
     124             :       {
     125       51200 :         unsigned long b;
     126       25465 :         ar( CEREAL_NVP_("data", b) );
     127             :         bits = std::bitset<N>( b );
     128       51200 :         break;
     129             :       }
     130             :       case bitset_detail::type::ullong:
     131       51200 :       {
     132             :         unsigned long long b;
     133        6400 :         ar( CEREAL_NVP_("data", b) );
     134        6400 :         bits = std::bitset<N>( b );
     135        6400 :         break;
     136             :       }
     137             :       case bitset_detail::type::string:
     138             :       {
     139             :         std::string b;
     140         200 :         ar( CEREAL_NVP_("data", b) );
     141           0 :         bits = std::bitset<N>( b );
     142         200 :         break;
     143         200 :       }
     144             :       case bitset_detail::type::bits:
     145         200 :       {
     146             :         // Normally we would use BinaryData to route this at compile time,
     147             :         // but doing this at runtime doesn't break any old serialization
     148         200 :         std::uint8_t chunk = 0;
     149         200 :         std::uint8_t mask  = 0;
     150             : 
     151             :         bits.reset();
     152       13200 : 
     153             :         // Load one chunk at a time, rotating through the chunk
     154       13000 :         // to set bits in the bitset
     155        6493 :         for( std::size_t i = 0; i < N; ++i )
     156             :         {
     157       13000 :           if( mask == 0 )
     158             :           {
     159             :             ar( chunk );
     160       13000 :             mask = 0x80;
     161             :           }
     162        1600 : 
     163        1600 :           if( chunk & mask )
     164        1600 :             bits[i] = 1;
     165             : 
     166             :           mask = static_cast<std::uint8_t>(mask >> 1);
     167             :         }
     168             :         break;
     169         200 :       }
     170         200 :       default:
     171         200 :         throw Exception("Invalid bitset data representation");
     172         400 :     }
     173             :   }
     174         400 : } // namespace cereal
     175             : 
     176             : #endif // CEREAL_TYPES_BITSET_HPP_

Generated by: LCOV version 1.13