Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / multiprecision / cpp_int / serialize.hpp
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
5
6 #ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP
7 #define BOOST_MP_CPP_INT_SERIALIZE_HPP
8
9 namespace boost {
10
11 namespace archive {
12
13 class binary_oarchive;
14 class binary_iarchive;
15
16 } // namespace archive
17
18 namespace serialization {
19
20 namespace mp = boost::multiprecision;
21
22 namespace cpp_int_detail {
23
24 using namespace boost::multiprecision;
25 using namespace boost::multiprecision::backends;
26
27 template <class T>
28 struct is_binary_archive : public mpl::false_
29 {};
30 template <>
31 struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_
32 {};
33 template <>
34 struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_
35 {};
36
37 //
38 // We have 8 serialization methods to fill out (and test), they are all permutations of:
39 // Load vs Store.
40 // Trivial or non-trivial cpp_int type.
41 // Binary or not archive.
42 //
43 template <class Archive, class Int>
44 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&)
45 {
46    // Load.
47    // Non-trivial.
48    // Non binary.
49
50    using boost::make_nvp;
51    bool        s;
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)
60    {
61       pl[i] = 0;
62       for (std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j)
63       {
64          unsigned char byte;
65          ar&           make_nvp("byte", byte);
66          pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT);
67          --byte_count;
68       }
69    }
70    if (s != val.sign())
71       val.negate();
72    val.normalize();
73 }
74 template <class Archive, class Int>
75 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&)
76 {
77    // Store.
78    // Non-trivial.
79    // Non binary.
80
81    using boost::make_nvp;
82    bool        s = val.sign();
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);
88
89    for (std::size_t i = 0; i < limb_count; ++i)
90    {
91       limb_type l = pl[i];
92       for (std::size_t j = 0; j < sizeof(limb_type); ++j)
93       {
94          unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1));
95          ar&           make_nvp("byte", byte);
96       }
97    }
98 }
99 template <class Archive, class Int>
100 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&)
101 {
102    // Load.
103    // Trivial.
104    // Non binary.
105    using boost::make_nvp;
106    bool                          s;
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)
112    {
113       unsigned char b;
114       ar&           make_nvp("byte", b);
115       l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT);
116    }
117    *val.limbs() = l;
118    if (s != val.sign())
119       val.negate();
120 }
121 template <class Archive, class Int>
122 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&)
123 {
124    // Store.
125    // Trivial.
126    // Non binary.
127    using boost::make_nvp;
128    bool                          s = val.sign();
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)
134    {
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);
137    }
138 }
139 template <class Archive, class Int>
140 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
141 {
142    // Load.
143    // Non-trivial.
144    // Binary.
145    bool        s;
146    std::size_t c;
147    ar&         s;
148    ar&         c;
149    val.resize(c, c);
150    ar.load_binary(val.limbs(), c * sizeof(limb_type));
151    if (s != val.sign())
152       val.negate();
153    val.normalize();
154 }
155 template <class Archive, class Int>
156 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
157 {
158    // Store.
159    // Non-trivial.
160    // Binary.
161    bool        s = val.sign();
162    std::size_t c = val.size();
163    ar&         s;
164    ar&         c;
165    ar.save_binary(val.limbs(), c * sizeof(limb_type));
166 }
167 template <class Archive, class Int>
168 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&)
169 {
170    // Load.
171    // Trivial.
172    // Binary.
173    bool s;
174    ar&  s;
175    ar.load_binary(val.limbs(), sizeof(*val.limbs()));
176    if (s != val.sign())
177       val.negate();
178 }
179 template <class Archive, class Int>
180 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&)
181 {
182    // Store.
183    // Trivial.
184    // Binary.
185    bool s = val.sign();
186    ar&  s;
187    ar.save_binary(val.limbs(), sizeof(*val.limbs()));
188 }
189
190 } // namespace cpp_int_detail
191
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*/)
194 {
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;
198
199    // Just dispatch to the correct method:
200    cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
201 }
202
203 } // namespace serialization
204 } // namespace boost
205
206 #endif // BOOST_MP_CPP_INT_SERIALIZE_HPP