1 ///////////////////////////////////////////////////////////////
2 // Copyright 2013 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
6 #ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP
7 #define BOOST_MP_CPP_INT_SERIALIZE_HPP
13 class binary_oarchive;
14 class binary_iarchive;
16 } // namespace archive
18 namespace serialization {
20 namespace mp = boost::multiprecision;
22 namespace cpp_int_detail {
24 using namespace boost::multiprecision;
25 using namespace boost::multiprecision::backends;
28 struct is_binary_archive : public mpl::false_
31 struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_
34 struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_
38 // We have 8 serialization methods to fill out (and test), they are all permutations of:
40 // Trivial or non-trivial cpp_int type.
41 // Binary or not archive.
43 template <class Archive, class Int>
44 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&)
50 using boost::make_nvp;
52 ar& make_nvp("sign", s);
53 std::size_t limb_count;
54 std::size_t byte_count;
55 ar& make_nvp("byte-count", byte_count);
56 limb_count = byte_count / sizeof(limb_type) + ((byte_count % sizeof(limb_type)) ? 1 : 0);
57 val.resize(limb_count, limb_count);
58 limb_type* pl = val.limbs();
59 for (std::size_t i = 0; i < limb_count; ++i)
62 for (std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j)
65 ar& make_nvp("byte", byte);
66 pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT);
74 template <class Archive, class Int>
75 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&)
81 using boost::make_nvp;
83 ar& make_nvp("sign", s);
84 limb_type* pl = val.limbs();
85 std::size_t limb_count = val.size();
86 std::size_t byte_count = limb_count * sizeof(limb_type);
87 ar& make_nvp("byte-count", byte_count);
89 for (std::size_t i = 0; i < limb_count; ++i)
92 for (std::size_t j = 0; j < sizeof(limb_type); ++j)
94 unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1));
95 ar& make_nvp("byte", byte);
99 template <class Archive, class Int>
100 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&)
105 using boost::make_nvp;
107 typename Int::local_limb_type l = 0;
108 ar& make_nvp("sign", s);
109 std::size_t byte_count;
110 ar& make_nvp("byte-count", byte_count);
111 for (std::size_t i = 0; i < byte_count; ++i)
114 ar& make_nvp("byte", b);
115 l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT);
121 template <class Archive, class Int>
122 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&)
127 using boost::make_nvp;
129 typename Int::local_limb_type l = *val.limbs();
130 ar& make_nvp("sign", s);
131 std::size_t limb_count = sizeof(l);
132 ar& make_nvp("byte-count", limb_count);
133 for (std::size_t i = 0; i < limb_count; ++i)
135 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));
136 ar& make_nvp("byte", b);
139 template <class Archive, class Int>
140 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
150 ar.load_binary(val.limbs(), c * sizeof(limb_type));
155 template <class Archive, class Int>
156 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
162 std::size_t c = val.size();
165 ar.save_binary(val.limbs(), c * sizeof(limb_type));
167 template <class Archive, class Int>
168 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&)
175 ar.load_binary(val.limbs(), sizeof(*val.limbs()));
179 template <class Archive, class Int>
180 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&)
187 ar.save_binary(val.limbs(), sizeof(*val.limbs()));
190 } // namespace cpp_int_detail
192 template <class Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator>
193 void serialize(Archive& ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/)
195 typedef typename Archive::is_saving save_tag;
196 typedef mpl::bool_<mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> trivial_tag;
197 typedef typename cpp_int_detail::is_binary_archive<Archive>::type binary_tag;
199 // Just dispatch to the correct method:
200 cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
203 } // namespace serialization
206 #endif // BOOST_MP_CPP_INT_SERIALIZE_HPP