serialize.hpp 7.0 KB

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