29 #ifndef PIRANHA_S11N_HPP 30 #define PIRANHA_S11N_HPP 33 #include <boost/algorithm/string/predicate.hpp> 34 #include <boost/archive/binary_iarchive.hpp> 35 #include <boost/archive/binary_oarchive.hpp> 36 #include <boost/archive/text_iarchive.hpp> 37 #include <boost/archive/text_oarchive.hpp> 38 #include <boost/iostreams/filtering_stream.hpp> 39 #include <boost/mpl/bool.hpp> 40 #include <boost/serialization/split_free.hpp> 41 #include <boost/serialization/split_member.hpp> 42 #include <boost/serialization/string.hpp> 43 #include <boost/version.hpp> 50 #include <type_traits> 53 #include <piranha/detail/demangle.hpp> 55 #include <piranha/is_key.hpp> 56 #include <piranha/safe_cast.hpp> 57 #include <piranha/symbol_utils.hpp> 68 using is_serialization_scalar
69 = disjunction<std::is_same<char, T>, std::is_same<signed char, T>, std::is_same<unsigned char, T>,
70 std::is_same<short, T>, std::is_same<unsigned short, T>, std::is_same<int, T>,
71 std::is_same<unsigned, T>, std::is_same<long, T>, std::is_same<unsigned long, T>,
72 std::is_same<long long, T>, std::is_same<unsigned long long, T>, std::is_same<float, T>,
73 std::is_same<double, T>, std::is_same<bool, T>>;
80 using is_saving_t =
typename A::is_saving;
83 using is_loading_t =
typename A::is_loading;
85 template <
typename A,
typename T>
86 using lshift_t = decltype(std::declval<A &>() << std::declval<const T &>());
88 template <
typename A,
typename T>
89 using and_t = decltype(std::declval<A &>() & std::declval<const T &>());
93 template <
typename A,
typename T>
94 using save_binary_t = decltype(std::declval<A &>().save_binary(std::declval<T *>(), std::declval<std::size_t>()));
96 template <
typename A,
typename T>
97 using register_type_t = decltype(std::declval<A &>().
template register_type<T>());
100 using get_library_version_t = decltype(std::declval<const A &>().get_library_version());
104 template <
typename A>
105 using get_helper_t_1 = decltype(std::declval<A &>().
template get_helper<helper>());
107 template <
typename A>
108 using get_helper_t_2 = decltype(std::declval<A &>().
template get_helper<helper>(static_cast<void *>(
nullptr)));
110 template <
typename Archive,
typename T>
112 = conjunction<std::is_same<detected_t<is_saving_t, uncvref_t<Archive>>, boost::mpl::bool_<true>>,
113 std::is_same<detected_t<is_loading_t, uncvref_t<Archive>>, boost::mpl::bool_<false>>,
116 std::is_same<detected_t<lshift_t, Archive, T>, addlref_t<Archive>>,
117 std::is_same<detected_t<and_t, Archive, T>, addlref_t<Archive>>,
118 is_detected<save_binary_t, Archive, unref_t<T>>, is_detected<register_type_t, Archive, uncvref_t<T>>,
124 std::is_convertible<detected_t<get_library_version_t, Archive>,
unsigned long long>
125 #if BOOST_VERSION >= 105700 128 is_detected<get_helper_t_1, Archive>, is_detected<get_helper_t_2, Archive>
140 template <
typename Archive,
typename T>
143 static const bool implementation_defined = ibsa_impl::impl<Archive, T>::value;
147 static const bool value = implementation_defined;
150 template <
typename Archive,
typename T>
153 inline namespace impl
160 template <
typename A,
typename T>
161 using rshift_t = decltype(std::declval<A &>() >> std::declval<T &>());
163 template <
typename A,
typename T>
164 using and_t = decltype(std::declval<A &>() & std::declval<T &>());
166 template <
typename A,
typename T>
167 using load_binary_t = decltype(std::declval<A &>().load_binary(std::declval<T *>(), std::declval<std::size_t>()));
169 template <
typename A,
typename T>
170 using reset_object_address_t
171 = decltype(std::declval<A &>().reset_object_address(std::declval<T *>(), std::declval<T *>()));
173 template <
typename A>
174 using delete_created_pointers_t = decltype(std::declval<A &>().delete_created_pointers());
176 template <
typename Archive,
typename T>
177 using impl = conjunction<
178 std::is_same<detected_t<ibsa_impl::is_saving_t, uncvref_t<Archive>>, boost::mpl::bool_<false>>,
179 std::is_same<detected_t<ibsa_impl::is_loading_t, uncvref_t<Archive>>, boost::mpl::bool_<true>>,
180 std::is_same<detected_t<rshift_t, Archive, T>, addlref_t<Archive>>,
181 std::is_same<detected_t<and_t, Archive, T>, addlref_t<Archive>>, is_detected<load_binary_t, Archive, unref_t<T>>,
182 is_detected<ibsa_impl::register_type_t, Archive, uncvref_t<T>>,
183 std::is_convertible<detected_t<ibsa_impl::get_library_version_t, Archive>,
unsigned long long>,
184 is_detected<reset_object_address_t, Archive, unref_t<T>>, is_detected<delete_created_pointers_t, Archive>
185 #if BOOST_VERSION >= 105700 187 is_detected<ibsa_impl::get_helper_t_1, Archive>, is_detected<ibsa_impl::get_helper_t_2, Archive>
199 template <
typename Archive,
typename T>
202 static const bool implementation_defined = ibla_impl::impl<Archive, T>::value;
206 static const bool value = implementation_defined;
209 template <
typename Archive,
typename T>
216 template <
typename Archive,
typename T>
244 template <
typename Archive,
typename T,
typename =
void>
248 inline namespace impl
252 template <
typename Archive,
typename T>
253 using boost_save_arithmetic_enabler =
259 enable_if_t<conjunction<is_boost_saving_archive<Archive, T>,
260 disjunction<is_serialization_scalar<T>, std::is_same<T, long double>>>::value>;
274 template <
typename Archive,
typename T>
278 inline namespace impl
282 template <
typename Archive>
283 using boost_save_string_enabler = enable_if_t<is_boost_saving_archive<Archive, std::string>::value>;
292 template <
typename Archive>
297 inline namespace impl
300 template <
typename Archive,
typename T>
304 template <
typename Archive,
typename T>
305 using boost_save_enabler
306 = enable_if_t<conjunction<is_boost_saving_archive<Archive, T>, is_detected<boost_save_impl_t, Archive, T>>::value,
327 template <
typename Archive,
typename T, boost_save_enabler<Archive, T> = 0>
333 inline namespace impl
336 template <
typename A,
typename T>
337 using boost_save_t = decltype(
piranha::boost_save(std::declval<A &>(), std::declval<const T &>()));
345 template <
typename Archive,
typename T>
348 static const bool implementation_defined = is_detected<boost_save_t, Archive, T>::value;
352 static const bool value = implementation_defined;
355 template <
typename Archive,
typename T>
362 template <
typename Archive,
typename T>
390 template <
typename Archive,
typename T,
typename =
void>
394 inline namespace impl
398 template <
typename Archive,
typename T>
399 using boost_load_arithmetic_enabler
400 = enable_if_t<conjunction<is_boost_loading_archive<Archive, T>,
401 disjunction<is_serialization_scalar<T>, std::is_same<T, long double>>>::value>;
415 template <
typename Archive,
typename T>
419 inline namespace impl
423 template <
typename Archive>
424 using boost_load_string_enabler = enable_if_t<is_boost_loading_archive<Archive, std::string>::value>;
433 template <
typename Archive>
438 inline namespace impl
441 template <
typename Archive,
typename T>
445 template <
typename Archive,
typename T>
446 using boost_load_enabler
447 = enable_if_t<conjunction<is_boost_loading_archive<Archive, T>, is_detected<boost_load_impl_t, Archive, T>>::value,
468 template <
typename Archive,
typename T, boost_load_enabler<Archive, T> = 0>
474 inline namespace impl
477 template <
typename A,
typename T>
478 using boost_load_t = decltype(
piranha::boost_load(std::declval<A &>(), std::declval<T &>()));
486 template <
typename Archive,
typename T>
489 static const bool implementation_defined = is_detected<boost_load_t, Archive, T>::value;
493 static const bool value = implementation_defined;
496 template <
typename Archive,
typename T>
513 template <
typename Key>
516 PIRANHA_TT_CHECK(
is_key, Key);
525 : m_key_m(
std::addressof(k)), m_key_c(m_key_m), m_ss(
ss)
534 : m_key_m(nullptr), m_key_c(
std::addressof(k)), m_ss(
ss)
548 if (unlikely(!m_key_m)) {
549 piranha_throw(std::runtime_error,
"trying to access the mutable key instance of a boost_s11n_key_wrapper " 550 "that was constructed with a const key");
578 #include <piranha/config.hpp> 580 #if defined(PIRANHA_WITH_MSGPACK) 582 #include <msgpack.hpp> 584 #if MSGPACK_VERSION_MAJOR < 2 586 #error The minimum msgpack-c version supported is 2. 592 #include <boost/iostreams/device/mapped_file.hpp> 606 template <
typename,
typename>
612 inline namespace impl
618 template <
typename Stream>
619 struct msgpack_stream_wrapper : Stream {
621 using Stream::Stream;
622 auto write(
const typename Stream::char_type *p, std::size_t count)
623 -> decltype(std::declval<Stream &>().write(p, std::streamsize(0)))
625 return static_cast<Stream *
>(
this)->write(p, safe_cast<std::streamsize>(count));
629 template <
typename T>
630 using msgpack_stream_write_t
631 = decltype(std::declval<T &>().write(std::declval<const char *>(), std::declval<std::size_t>()));
644 template <
typename T>
647 static const bool implementation_defined
648 = conjunction<is_detected<msgpack_stream_write_t, T>, negation<std::is_reference<T>>,
649 negation<std::is_const<T>>>
::value;
653 static const bool value = implementation_defined;
656 template <
typename T>
685 template <
typename Stream,
typename T,
typename =
void>
689 inline namespace impl
692 template <
typename Stream,
typename T>
693 using msgpack_scalar_enabler = enable_if_t<conjunction<is_msgpack_stream<Stream>, is_serialization_scalar<T>>::value>;
710 template <
typename Stream,
typename T>
725 inline namespace impl
728 template <
typename Stream>
729 using msgpack_ld_enabler
730 = enable_if_t<conjunction<is_msgpack_stream<Stream>, has_msgpack_pack<Stream, std::string>>::value>;
740 template <
typename Stream>
758 packer.pack_bin(
sizeof(
long double));
759 packer.pack_bin_body(reinterpret_cast<const char *>(&x),
sizeof(
long double));
762 if (std::signbit(x)) {
767 }
else if (std::isinf(x)) {
768 if (std::signbit(x)) {
774 std::ostringstream oss;
776 oss.imbue(std::locale::classic());
778 oss << std::scientific;
786 oss.precision(std::numeric_limits<long double>::max_digits10);
794 inline namespace impl
797 template <
typename Stream>
798 using msgpack_string_enabler = enable_if_t<is_msgpack_stream<Stream>::value>;
808 template <
typename Stream>
823 inline namespace impl
826 template <
typename Stream,
typename T>
827 using msgpack_pack_impl_t = decltype(msgpack_pack_impl<Stream, T>{}(
828 std::declval<msgpack::packer<Stream> &>(), std::declval<const T &>(), std::declval<msgpack_format>()));
831 template <
typename Stream,
typename T>
832 using msgpack_pack_enabler
833 = enable_if_t<conjunction<is_msgpack_stream<Stream>, is_detected<msgpack_pack_impl_t, Stream, T>>::value,
int>;
855 template <
typename Stream,
typename T, msgpack_pack_enabler<Stream, T> = 0>
866 template <
typename T,
typename =
void>
870 inline namespace impl
873 template <
typename T>
874 using msgpack_convert_scalar_enabler = enable_if_t<is_serialization_scalar<T>::value>;
890 template <
typename T>
924 inline namespace impl
927 template <
typename T>
928 using msgpack_convert_impl_t = decltype(msgpack_convert_impl<T>{}(
929 std::declval<T &>(), std::declval<const msgpack::object &>(), std::declval<msgpack_format>()));
932 template <
typename T>
933 using msgpack_convert_enabler
934 = enable_if_t<conjunction<negation<std::is_const<T>>, is_detected<msgpack_convert_impl_t, T>>::value,
int>;
956 template <
typename T, msgpack_convert_enabler<T> = 0>
962 inline namespace impl
965 template <
typename T>
966 using msgpack_convert_ld_enabler
967 = enable_if_t<conjunction<std::is_same<T, long double>, has_msgpack_convert<std::string>>::value>;
976 template <
typename T>
992 using lim = std::numeric_limits<long double>;
994 std::array<char, sizeof(long double)> tmp;
996 std::copy(tmp.begin(), tmp.end(),
reinterpret_cast<char *
>(&x));
998 PIRANHA_MAYBE_TLS std::string tmp;
1000 if (tmp ==
"+nan") {
1001 if (lim::has_quiet_NaN) {
1002 x = std::copysign(lim::quiet_NaN(), 1.l);
1004 piranha_throw(std::invalid_argument,
"cannot deserialize a NaN if the platform does not support " 1007 }
else if (tmp ==
"-nan") {
1008 if (lim::has_quiet_NaN) {
1009 x = std::copysign(lim::quiet_NaN(), -1.l);
1011 piranha_throw(std::invalid_argument,
"cannot deserialize a NaN if the platform does not support " 1014 }
else if (tmp ==
"+inf") {
1015 if (lim::has_infinity) {
1016 x = lim::infinity();
1018 piranha_throw(std::invalid_argument,
"infinities are not supported by the platform");
1020 }
else if (tmp ==
"-inf") {
1021 if (lim::has_infinity) {
1022 x = std::copysign(lim::infinity(), -1.l);
1024 piranha_throw(std::invalid_argument,
"infinities are not supported by the platform");
1027 std::istringstream iss;
1028 iss.imbue(std::locale::classic());
1032 iss >> std::scientific;
1035 if (unlikely(iss.fail())) {
1036 piranha_throw(std::invalid_argument,
"failed to parse the string '" + tmp +
"' as a long double");
1043 inline namespace impl
1046 template <
typename Stream,
typename T>
1048 std::declval<const T &>(), std::declval<msgpack_format>()));
1056 template <
typename Stream,
typename T>
1057 class has_msgpack_pack
1059 static const bool implementation_defined = is_detected<msgpack_pack_t, Stream, T>::value;
1063 static const bool value = implementation_defined;
1066 template <
typename Stream,
typename T>
1069 inline namespace impl
1072 template <
typename T>
1074 std::declval<T &>(), std::declval<const msgpack::object &>(), std::declval<msgpack_format>()));
1081 template <
typename T>
1082 class has_msgpack_convert
1084 static const bool implementation_defined = is_detected<msgpack_convert_t, T>::value;
1088 static const bool value = implementation_defined;
1091 template <
typename T>
1094 inline namespace impl
1097 template <
typename Stream,
typename Key>
1098 using key_msgpack_pack_t = decltype(std::declval<const Key &>().
msgpack_pack(
1099 std::declval<msgpack::packer<Stream> &>(), std::declval<msgpack_format>(), std::declval<const symbol_fset &>()));
1114 template <
typename Stream,
typename Key>
1117 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
1118 static const bool implementation_defined
1123 static const bool value = implementation_defined;
1126 template <
typename Stream,
typename Key>
1129 inline namespace impl
1132 template <
typename Key>
1133 using key_msgpack_convert_t = decltype(std::declval<Key &>().
msgpack_convert(
1134 std::declval<const msgpack::object &>(), std::declval<msgpack_format>(), std::declval<const symbol_fset &>()));
1148 template <
typename Key>
1151 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
1152 static const bool implementation_defined = is_detected<key_msgpack_convert_t, Key>::value;
1156 static const bool value = implementation_defined;
1159 template <
typename Key>
1165 #if defined(PIRANHA_WITH_ZLIB) 1167 #include <boost/iostreams/filter/gzip.hpp> 1168 #include <boost/iostreams/filter/zlib.hpp> 1170 #define PIRANHA_ZLIB_CONDITIONAL(expr) expr 1174 #define PIRANHA_ZLIB_CONDITIONAL(expr) piranha_throw(not_implemented_error, "zlib support is not enabled") 1178 #if defined(PIRANHA_WITH_BZIP2) 1180 #include <boost/iostreams/filter/bzip2.hpp> 1182 #define PIRANHA_BZIP2_CONDITIONAL(expr) expr 1186 #define PIRANHA_BZIP2_CONDITIONAL(expr) piranha_throw(not_implemented_error, "bzip2 support is not enabled") 1243 inline namespace impl
1247 template <
typename CompressionFilter,
typename T>
1248 inline void save_file_boost_compress_impl(
const T &x, std::ofstream &ofile,
data_format f)
1259 boost::iostreams::filtering_ostream out;
1260 out.push(CompressionFilter{});
1263 boost::archive::binary_oarchive oa(out);
1266 boost::archive::text_oarchive oa(out);
1272 template <
typename DecompressionFilter,
typename T>
1273 inline void load_file_boost_compress_impl(T &x, std::ifstream &ifile,
data_format f)
1276 boost::iostreams::filtering_istream in;
1277 in.push(DecompressionFilter{});
1280 boost::archive::binary_iarchive ia(in);
1283 boost::archive::text_iarchive ia(in);
1289 template <
typename T, enable_if_t<conjunction<has_boost_save<boost::archive::binary_oarchive, T>,
1290 has_boost_save<boost::archive::text_oarchive, T>>::value,
1294 namespace bi = boost::iostreams;
1296 std::ofstream ofile(filename, std::ios::out | std::ios::binary | std::ios::trunc);
1297 if (unlikely(!ofile.good())) {
1298 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for saving");
1302 PIRANHA_BZIP2_CONDITIONAL(save_file_boost_compress_impl<bi::bzip2_compressor>(x, ofile, f));
1305 PIRANHA_ZLIB_CONDITIONAL(save_file_boost_compress_impl<bi::gzip_compressor>(x, ofile, f));
1308 PIRANHA_ZLIB_CONDITIONAL(save_file_boost_compress_impl<bi::zlib_compressor>(x, ofile, f));
1312 boost::archive::binary_oarchive oa(ofile);
1315 boost::archive::text_oarchive oa(ofile);
1321 template <
typename T, enable_if_t<disjunction<negation<has_boost_save<boost::archive::binary_oarchive, T>>,
1322 negation<has_boost_save<boost::archive::text_oarchive, T>>>::value,
1327 "type '" + detail::demangle<T>() +
"' does not support serialization via Boost");
1330 template <
typename T, enable_if_t<conjunction<has_boost_load<boost::archive::binary_iarchive, T>,
1331 has_boost_load<boost::archive::text_iarchive, T>>::value,
1335 namespace bi = boost::iostreams;
1336 std::ifstream ifile(filename, std::ios::in | std::ios::binary);
1337 if (unlikely(!ifile.good())) {
1338 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for loading");
1342 PIRANHA_BZIP2_CONDITIONAL(load_file_boost_compress_impl<bi::bzip2_decompressor>(x, ifile, f));
1345 PIRANHA_ZLIB_CONDITIONAL(load_file_boost_compress_impl<bi::gzip_decompressor>(x, ifile, f));
1348 PIRANHA_ZLIB_CONDITIONAL(load_file_boost_compress_impl<bi::zlib_decompressor>(x, ifile, f));
1352 boost::archive::binary_iarchive ia(ifile);
1355 boost::archive::text_iarchive ia(ifile);
1361 template <
typename T, enable_if_t<disjunction<negation<has_boost_load<boost::archive::binary_iarchive, T>>,
1362 negation<has_boost_load<boost::archive::text_iarchive, T>>>::value,
1367 "type '" + detail::demangle<T>() +
"' does not support deserialization via Boost");
1370 #if defined(PIRANHA_WITH_MSGPACK) 1373 template <
typename CompressionFilter,
typename T>
1374 inline void save_file_msgpack_compress_impl(
const T &x, msgpack_stream_wrapper<std::ofstream> &ofile,
msgpack_format mf)
1376 msgpack_stream_wrapper<boost::iostreams::filtering_ostream> out;
1377 out.push(CompressionFilter{});
1379 msgpack::packer<decltype(out)> packer(out);
1383 template <
typename DecompressionFilter,
typename T>
1384 inline void load_file_msgpack_compress_impl(T &x,
const std::string &filename,
msgpack_format mf)
1386 std::ifstream ifile(filename, std::ios::in | std::ios::binary);
1387 if (unlikely(!ifile.good())) {
1388 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for loading");
1390 std::vector<char> vchar;
1391 boost::iostreams::filtering_istream in;
1392 in.push(DecompressionFilter{});
1394 std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(vchar));
1395 auto oh = msgpack::unpack(vchar.data(),
safe_cast<std::size_t>(vchar.size()));
1402 enable_if_t<conjunction<has_msgpack_pack<msgpack_stream_wrapper<std::ofstream>, T>,
1403 has_msgpack_pack<msgpack_stream_wrapper<boost::iostreams::filtering_ostream>, T>>::value,
1405 inline void save_file_msgpack_impl(
const T &x,
const std::string &filename,
data_format f,
compression c)
1407 namespace bi = boost::iostreams;
1409 msgpack_stream_wrapper<std::ofstream> ofile(filename, std::ios::out | std::ios::binary | std::ios::trunc);
1410 if (unlikely(!ofile.good())) {
1411 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for saving");
1415 PIRANHA_BZIP2_CONDITIONAL(save_file_msgpack_compress_impl<bi::bzip2_compressor>(x, ofile, mf));
1418 PIRANHA_ZLIB_CONDITIONAL(save_file_msgpack_compress_impl<bi::gzip_compressor>(x, ofile, mf));
1421 PIRANHA_ZLIB_CONDITIONAL(save_file_msgpack_compress_impl<bi::zlib_compressor>(x, ofile, mf));
1424 msgpack::packer<decltype(ofile)> packer(ofile);
1433 disjunction<negation<has_msgpack_pack<msgpack_stream_wrapper<std::ofstream>, T>>,
1434 negation<has_msgpack_pack<msgpack_stream_wrapper<boost::iostreams::filtering_ostream>, T>>>::value,
1439 "type '" + detail::demangle<T>() +
"' does not support serialization via msgpack");
1442 template <typename T, enable_if_t<has_msgpack_convert<T>::value,
int> = 0>
1445 namespace bi = boost::iostreams;
1449 PIRANHA_BZIP2_CONDITIONAL(load_file_msgpack_compress_impl<bi::bzip2_decompressor>(x, filename, mf));
1452 PIRANHA_ZLIB_CONDITIONAL(load_file_msgpack_compress_impl<bi::gzip_decompressor>(x, filename, mf));
1455 PIRANHA_ZLIB_CONDITIONAL(load_file_msgpack_compress_impl<bi::zlib_decompressor>(x, filename, mf));
1459 std::unique_ptr<bi::mapped_file> mmap;
1461 mmap.reset(
new bi::mapped_file(filename, bi::mapped_file::readonly));
1465 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for loading");
1468 if (unlikely(!mmap->is_open())) {
1469 piranha_throw(std::runtime_error,
"file '" + filename +
"' could not be opened for loading");
1471 auto oh = msgpack::unpack(mmap->const_data(),
safe_cast<std::size_t>(mmap->size()));
1477 template <typename T, enable_if_t<!has_msgpack_convert<T>::value,
int> = 0>
1481 "type '" + detail::demangle<T>() +
"' does not support deserialization via msgpack");
1487 template <
typename T>
1490 piranha_throw(not_implemented_error,
"msgpack support is not enabled");
1493 template <
typename T>
1496 piranha_throw(not_implemented_error,
"msgpack support is not enabled");
1502 template <
typename T>
1503 using load_file_enabler = enable_if_t<!std::is_const<T>::value,
int>;
1506 inline std::pair<compression, data_format> get_cdf_from_filename(std::string filename)
1508 const auto orig_fname = filename;
1510 if (boost::ends_with(filename,
".bz2")) {
1512 filename.erase(filename.end() - 4, filename.end());
1513 }
else if (boost::ends_with(filename,
".gz")) {
1515 filename.erase(filename.end() - 3, filename.end());
1516 }
else if (boost::ends_with(filename,
".zip")) {
1518 filename.erase(filename.end() - 4, filename.end());
1521 if (boost::ends_with(filename,
".boostb")) {
1523 }
else if (boost::ends_with(filename,
".boostp")) {
1525 }
else if (boost::ends_with(filename,
".mpackb")) {
1527 }
else if (boost::ends_with(filename,
".mpackp")) {
1531 "unable to deduce the data format from the filename '" + orig_fname
1532 +
"'. The filename must end with one of ['.boostb','.boostp','.mpackb','.mpackp'], " 1533 "optionally followed by one of ['.bz2','gz','zip'].");
1535 return std::make_pair(c, f);
1564 template <
typename T>
1568 save_file_boost_impl(x, filename, f, c);
1570 save_file_msgpack_impl(x, filename, f, c);
1600 template <
typename T>
1601 inline void save_file(
const T &x,
const std::string &filename)
1603 const auto p = get_cdf_from_filename(filename);
1604 save_file(x, filename, p.second, p.first);
1637 template <
typename T, load_file_enabler<T> = 0>
1641 load_file_boost_impl(x, filename, f, c);
1643 load_file_msgpack_impl(x, filename, f, c);
1662 template <
typename T, load_file_enabler<T> = 0>
1665 const auto p = get_cdf_from_filename(filename);
1666 load_file(x, filename, p.second, p.first);
1669 inline namespace impl
1672 #if defined(PIRANHA_WITH_MSGPACK) 1676 template <
typename Stream,
typename T>
1677 using msgpack_pack_member_t = decltype(
1678 std::declval<const T &>().
msgpack_pack(std::declval<msgpack::packer<Stream> &>(), std::declval<msgpack_format>()));
1680 template <
typename T>
1681 using msgpack_convert_member_t = decltype(
1682 std::declval<T &>().
msgpack_convert(std::declval<const msgpack::object &>(), std::declval<msgpack_format>()));
1687 template <
typename Archive,
typename It>
1688 inline void boost_save_range(Archive &ar, It begin, It end)
1690 for (; begin != end; ++begin) {
1695 template <
typename Archive,
typename V>
1696 inline void boost_save_vector(Archive &ar,
const V &v)
1699 boost_save_range(ar, v.begin(), v.end());
1702 template <
typename Archive,
typename It>
1703 inline void boost_load_range(Archive &ar, It begin, It end)
1705 for (; begin != end; ++begin) {
1710 template <
typename Archive,
typename V>
1711 inline void boost_load_vector(Archive &ar, V &v)
1713 typename V::size_type size;
1716 boost_load_range(ar, v.begin(), v.end());
1720 template <
typename Archive,
typename V,
typename T =
void>
1721 using boost_save_vector_enabler = enable_if_t<
1722 conjunction<has_boost_save<Archive, typename V::value_type>, has_boost_save<Archive, typename V::size_type>>::value,
1725 template <
typename Archive,
typename V,
typename T =
void>
1726 using boost_load_vector_enabler = enable_if_t<
1727 conjunction<has_boost_load<Archive, typename V::value_type>, has_boost_load<Archive, typename V::size_type>>::value,
1730 #if defined(PIRANHA_WITH_MSGPACK) 1732 template <
typename Stream,
typename It,
typename Size>
1733 inline void msgpack_pack_range(msgpack::packer<Stream> &p, It begin, It end, Size s,
msgpack_format f)
1735 p.pack_array(safe_cast<std::uint32_t>(s));
1736 for (; begin != end; ++begin) {
1741 template <
typename Stream,
typename V>
1742 inline void msgpack_pack_vector(msgpack::packer<Stream> &p,
const V &v,
msgpack_format f)
1744 msgpack_pack_range(p, v.begin(), v.end(), v.size(), f);
1748 template <
typename V>
1749 inline void msgpack_convert_array(
const msgpack::object &o, V &v,
msgpack_format f)
1752 PIRANHA_MAYBE_TLS std::vector<msgpack::object> tmp_obj;
1754 v.resize(
safe_cast<decltype(v.size())>(tmp_obj.size()));
1755 for (decltype(v.size()) i = 0; i < v.size(); ++i) {
1760 template <
typename Stream,
typename V,
typename T =
void>
1761 using msgpack_pack_vector_enabler
1762 = enable_if_t<conjunction<is_msgpack_stream<Stream>, has_msgpack_pack<Stream, typename V::value_type>,
1763 has_safe_cast<std::uint32_t,
typename V::size_type>>::value,
1766 template <
typename V,
typename T =
void>
1767 using msgpack_convert_array_enabler
1768 = enable_if_t<conjunction<has_safe_cast<typename V::size_type, typename std::vector<msgpack::object>::size_type>,
1769 has_msgpack_convert<typename V::value_type>>::value,
1776 #undef PIRANHA_ZLIB_CONDITIONAL 1778 #undef PIRANHA_BZIP2_CONDITIONAL static const bool value
Value of the type trait.
void operator()(msgpack::packer< Stream > &packer, const T &x, msgpack_format) const
Call operator.
static const bool value
Value of the type trait.
boost_s11n_key_wrapper(const Key &k, const symbol_fset &ss)
Constructor from const key and piranha::symbol_fset.
void operator()(long double &x, const msgpack::object &o, msgpack_format f) const
Call operator.
void boost_load(Archive &ar, T &x)
Load from Boost archive.
Detect Boost saving archives.
Default implementation of piranha::boost_load().
void msgpack_convert(T &x, const msgpack::object &o, msgpack_format f)
Convert msgpack object.
void save_file(const T &x, const std::string &filename, data_format f, compression c)
Save to file.
static const bool value
Value of the type trait.
Implementation of piranha::boost_load() via the Boost API.
Default implementation of piranha::boost_save().
Detect Boost loading archives.
Detect the presence of piranha::boost_load().
static const bool value
Value of the type trait.
Detect the presence of piranha::msgpack_convert().
Detect the presence of the msgpack_convert() method in keys.
void load_file(T &x, const std::string &filename, data_format f, compression c)
Load from file.
Default functor for the implementation of piranha::msgpack_convert().
void operator()(std::string &s, const msgpack::object &o, msgpack_format) const
Call operator.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
boost::container::flat_set< std::string > symbol_fset
Flat set of symbols.
Detect the presence of piranha::boost_save().
const Key & key() const
Const reference to the key.
Default functor for the implementation of piranha::msgpack_pack().
Wrapper for the serialization of keys via Boost.
msgpack_format
Serialization format for msgpack.
void operator()(msgpack::packer< Stream > &packer, const std::string &s, msgpack_format) const
Call operator.
static const bool value
Value of the type trait.
boost_s11n_key_wrapper(Key &k, const symbol_fset &ss)
Constructor from key and piranha::symbol_fset.
static const bool value
Value of the type trait.
Key & key()
Reference to the key.
static const bool value
Value of the type trait.
Implementation of piranha::boost_save() via the Boost API.
void msgpack_pack(msgpack::packer< Stream > &packer, const T &x, msgpack_format f)
Pack generic object in a msgpack stream.
Detect the presence of piranha::msgpack_pack().
void operator()(Archive &ar, T &x) const
Call operator.
Detect the presence of the msgpack_pack() method in keys.
void operator()(Archive &ar, const T &x) const
Call operator.
static const bool value
Value of the type trait.
void operator()(msgpack::packer< Stream > &packer, const long double &x, msgpack_format f) const
Call operator.
void boost_save(Archive &ar, const T &x)
Save to Boost archive.
static const bool value
Value of the type trait.
compression
Compression format.
const symbol_fset & ss() const
Const reference to the symbol set.
void operator()(T &x, const msgpack::object &o, msgpack_format) const
Call operator.
safe_cast_type< To, From > safe_cast(const From &x)
Safe cast.