LCOV - code coverage report
Current view: top level - cereal/types - bitset.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 58 86.2 %
Date: 2022-01-16 21:05:07 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 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_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        1000 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
      57             :   {
      58        1000 :     ar( CEREAL_NVP_("type", bitset_detail::type::bits) );
      59             : 
      60             :     // Serialize 8 bit chunks
      61        1000 :     std::uint8_t chunk = 0;
      62        1000 :     std::uint8_t mask = 0x80;
      63             : 
      64             :     // Set each chunk using a rotating mask for the current bit
      65      180400 :     for( std::size_t i = 0; i < N; ++i )
      66             :     {
      67      179400 :       if( bits[i] )
      68       86476 :         chunk |= mask;
      69             : 
      70      179400 :       mask = static_cast<std::uint8_t>(mask >> 1);
      71             : 
      72             :       // output current chunk when mask is empty (8 bits)
      73      179400 :       if( mask == 0 )
      74             :       {
      75       22400 :         ar( chunk );
      76       22400 :         chunk = 0;
      77       22400 :         mask = 0x80;
      78             :       }
      79             :     }
      80             : 
      81             :     // serialize remainder, if it exists
      82        1000 :     if( mask != 0x80 )
      83         200 :       ar( chunk );
      84        1000 :   }
      85             : 
      86             :   //! Serializing (save) for std::bitset when BinaryData is not supported
      87             :   template <class Archive, size_t N,
      88             :             traits::DisableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
      89             :             = traits::sfinae> inline
      90        1000 :   void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
      91             :   {
      92             :     try
      93             :     {
      94        1000 :       auto const b = bits.to_ulong();
      95         498 :       ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
      96         498 :       ar( CEREAL_NVP_("data", b) );
      97             :     }
      98        1004 :     catch( std::overflow_error const & )
      99             :     {
     100             :       try
     101             :       {
     102         502 :         auto const b = bits.to_ullong();
     103           0 :         ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
     104           0 :         ar( CEREAL_NVP_("data", b) );
     105             :       }
     106         502 :       catch( std::overflow_error const & )
     107             :       {
     108         502 :         ar( CEREAL_NVP_("type", bitset_detail::type::string) );
     109         502 :         ar( CEREAL_NVP_("data", bits.to_string()) );
     110             :       }
     111             :     }
     112        1000 :   }
     113             : 
     114             :   //! Serializing (load) for std::bitset
     115             :   template <class Archive, size_t N> inline
     116        2000 :   void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
     117             :   {
     118             :     bitset_detail::type t;
     119        2000 :     ar( CEREAL_NVP_("type", t) );
     120             : 
     121        2000 :     switch( t )
     122             :     {
     123         498 :       case bitset_detail::type::ulong:
     124             :       {
     125             :         unsigned long b;
     126         498 :         ar( CEREAL_NVP_("data", b) );
     127         498 :         bits = std::bitset<N>( b );
     128         498 :         break;
     129             :       }
     130           0 :       case bitset_detail::type::ullong:
     131             :       {
     132             :         unsigned long long b;
     133           0 :         ar( CEREAL_NVP_("data", b) );
     134           0 :         bits = std::bitset<N>( b );
     135           0 :         break;
     136             :       }
     137         502 :       case bitset_detail::type::string:
     138             :       {
     139        1004 :         std::string b;
     140         502 :         ar( CEREAL_NVP_("data", b) );
     141         502 :         bits = std::bitset<N>( b );
     142         502 :         break;
     143             :       }
     144        1000 :       case bitset_detail::type::bits:
     145             :       {
     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        1000 :         std::uint8_t chunk = 0;
     149        1000 :         std::uint8_t mask  = 0;
     150             : 
     151        1000 :         bits.reset();
     152             : 
     153             :         // Load one chunk at a time, rotating through the chunk
     154             :         // to set bits in the bitset
     155      180400 :         for( std::size_t i = 0; i < N; ++i )
     156             :         {
     157      179400 :           if( mask == 0 )
     158             :           {
     159       22600 :             ar( chunk );
     160       22600 :             mask = 0x80;
     161             :           }
     162             : 
     163      179400 :           if( chunk & mask )
     164       86476 :             bits[i] = 1;
     165             : 
     166      179400 :           mask = static_cast<std::uint8_t>(mask >> 1);
     167             :         }
     168        1000 :         break;
     169             :       }
     170           0 :       default:
     171           0 :         throw Exception("Invalid bitset data representation");
     172             :     }
     173        2000 :   }
     174             : } // namespace cereal
     175             : 
     176             : #endif // CEREAL_TYPES_BITSET_HPP_

Generated by: LCOV version 1.14