serialize.hpp 7.1 KB

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