200 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			200 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////// | ||
|  | //  Copyright 2013 John Maddock. Distributed under the Boost | ||
|  | //  Software License, Version 1.0. (See accompanying file | ||
|  | //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ | ||
|  | 
 | ||
|  | #ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP | ||
|  | #define BOOST_MP_CPP_INT_SERIALIZE_HPP | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | 
 | ||
|  | namespace archive{ | ||
|  | 
 | ||
|  | class binary_oarchive; | ||
|  | class binary_iarchive; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | namespace serialization { | ||
|  | 
 | ||
|  | namespace mp = boost::multiprecision; | ||
|  | 
 | ||
|  | namespace cpp_int_detail{ | ||
|  | 
 | ||
|  | using namespace boost::multiprecision; | ||
|  | using namespace boost::multiprecision::backends; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_binary_archive : public mpl::false_ {}; | ||
|  | template <> | ||
|  | struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_ {}; | ||
|  | template <> | ||
|  | struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_ {}; | ||
|  | 
 | ||
|  | // | ||
|  | // We have 8 serialization methods to fill out (and test), they are all permutations of: | ||
|  | // Load vs Store. | ||
|  | // Trivial or non-trivial cpp_int type. | ||
|  | // Binary or not archive. | ||
|  | // | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&) | ||
|  | { | ||
|  |    // Load. | ||
|  |    // Non-trivial. | ||
|  |    // Non binary. | ||
|  | 
 | ||
|  |    bool s; | ||
|  |    ar & s; | ||
|  |    std::size_t limb_count; | ||
|  |    std::size_t byte_count; | ||
|  |    ar & byte_count; | ||
|  |    limb_count = byte_count / sizeof(limb_type) + ((byte_count % sizeof(limb_type)) ? 1 : 0); | ||
|  |    val.resize(limb_count, limb_count); | ||
|  |    limb_type* pl = val.limbs(); | ||
|  |    for(std::size_t i = 0; i < limb_count; ++i) | ||
|  |    { | ||
|  |       pl[i] = 0; | ||
|  |       for(std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j) | ||
|  |       { | ||
|  |          unsigned char byte; | ||
|  |          ar & byte; | ||
|  |          pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT); | ||
|  |          --byte_count; | ||
|  |       } | ||
|  |    } | ||
|  |    if(s != val.sign()) | ||
|  |       val.negate(); | ||
|  |    val.normalize(); | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&) | ||
|  | { | ||
|  |    // Store. | ||
|  |    // Non-trivial. | ||
|  |    // Non binary. | ||
|  | 
 | ||
|  |    bool s = val.sign(); | ||
|  |    ar & s; | ||
|  |    limb_type* pl = val.limbs(); | ||
|  |    std::size_t limb_count = val.size(); | ||
|  |    std::size_t byte_count = limb_count * sizeof(limb_type); | ||
|  |    ar & byte_count; | ||
|  | 
 | ||
|  |    for(std::size_t i = 0; i < limb_count; ++i) | ||
|  |    { | ||
|  |       limb_type l = pl[i]; | ||
|  |       for(std::size_t j = 0; j < sizeof(limb_type); ++j) | ||
|  |       { | ||
|  |          unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1)); | ||
|  |          ar & byte; | ||
|  |       } | ||
|  |    } | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&) | ||
|  | { | ||
|  |    // Load. | ||
|  |    // Trivial. | ||
|  |    // Non binary. | ||
|  |    bool s; | ||
|  |    typename Int::local_limb_type l = 0; | ||
|  |    ar & s; | ||
|  |    std::size_t byte_count; | ||
|  |    ar & byte_count; | ||
|  |    for(std::size_t i = 0; i < byte_count; ++i) | ||
|  |    { | ||
|  |       unsigned char b; | ||
|  |       ar & b; | ||
|  |       l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT); | ||
|  |    } | ||
|  |    *val.limbs() = l; | ||
|  |    if(s != val.sign()) | ||
|  |       val.negate(); | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&) | ||
|  | { | ||
|  |    // Store. | ||
|  |    // Trivial. | ||
|  |    // Non binary. | ||
|  |    bool s = val.sign(); | ||
|  |    typename Int::local_limb_type l = *val.limbs(); | ||
|  |    ar & s; | ||
|  |    std::size_t limb_count = sizeof(l); | ||
|  |    ar & limb_count; | ||
|  |    for(std::size_t i = 0; i < limb_count; ++i) | ||
|  |    { | ||
|  |       unsigned char b = static_cast<unsigned char>(static_cast<typename Int::local_limb_type>(l >> (i * CHAR_BIT)) & static_cast<typename Int::local_limb_type>((1u << CHAR_BIT) - 1)); | ||
|  |       ar & b; | ||
|  |    } | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&) | ||
|  | { | ||
|  |    // Load. | ||
|  |    // Non-trivial. | ||
|  |    // Binary. | ||
|  |    bool s; | ||
|  |    std::size_t c; | ||
|  |    ar & s; | ||
|  |    ar & c; | ||
|  |    val.resize(c, c); | ||
|  |    ar.load_binary(val.limbs(), c * sizeof(limb_type)); | ||
|  |    if(s != val.sign()) | ||
|  |       val.negate(); | ||
|  |    val.normalize(); | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&) | ||
|  | { | ||
|  |    // Store. | ||
|  |    // Non-trivial. | ||
|  |    // Binary. | ||
|  |    bool s = val.sign(); | ||
|  |    std::size_t c = val.size(); | ||
|  |    ar & s; | ||
|  |    ar & c; | ||
|  |    ar.save_binary(val.limbs(), c * sizeof(limb_type)); | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&) | ||
|  | { | ||
|  |    // Load. | ||
|  |    // Trivial. | ||
|  |    // Binary. | ||
|  |    bool s; | ||
|  |    ar & s; | ||
|  |    ar.load_binary(val.limbs(), sizeof(*val.limbs())); | ||
|  |    if(s != val.sign()) | ||
|  |       val.negate(); | ||
|  | } | ||
|  | template <class Archive, class Int> | ||
|  | void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&) | ||
|  | { | ||
|  |    // Store. | ||
|  |    // Trivial. | ||
|  |    // Binary. | ||
|  |    bool s = val.sign(); | ||
|  |    ar & s; | ||
|  |    ar.save_binary(val.limbs(), sizeof(*val.limbs())); | ||
|  | } | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | template<class Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator> | ||
|  | void serialize(Archive & ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/) | ||
|  | { | ||
|  |    typedef typename Archive::is_saving save_tag; | ||
|  |    typedef mpl::bool_<mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> trivial_tag; | ||
|  |    typedef typename cpp_int_detail::is_binary_archive<Archive>::type binary_tag; | ||
|  | 
 | ||
|  |    // Just dispatch to the correct method: | ||
|  |    cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag()); | ||
|  | } | ||
|  | 
 | ||
|  | }} // namespaces | ||
|  | 
 | ||
|  | #endif // BOOST_MP_CPP_INT_SERIALIZE_HPP | ||
|  | 
 |