Created
November 23, 2022 08:35
-
-
Save cdcseacave/dd8c7bd64f6559cf10d3b0143a42743a to your computer and use it in GitHub Desktop.
Example using Boost serialization with ZSTD or ZIP compression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CMakeList.txt : Top-level CMake project file, do global configuration | |
cmake_minimum_required (VERSION 3.8.2) | |
# Load automatically VCPKG toolchain if available | |
IF(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED ENV{VCPKG_ROOT}) | |
SET(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") | |
IF(NOT DEFINED VCPKG_TARGET_TRIPLET AND DEFINED ENV{VCPKG_DEFAULT_TRIPLET}) | |
SET(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "") | |
ENDIF() | |
ENDIF() | |
project ("ReproBoostZstd") | |
FIND_PACKAGE(Boost COMPONENTS iostreams serialization REQUIRED) | |
if(Boost_FOUND) | |
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) | |
ADD_DEFINITIONS(${Boost_DEFINITIONS}) | |
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) | |
endif() | |
# Add source to this project's executable. | |
add_executable(ReproBoostZstd "ReproBoostZstd.cpp") | |
# Link its dependencies | |
target_link_libraries(ReproBoostZstd PRIVATE Boost::boost Boost::serialization Boost::iostreams) | |
#or target_link_libraries(ReproBoostZstd ${Boost_LIBRARIES}) | |
if (CMAKE_VERSION VERSION_GREATER 3.12) | |
set_property(TARGET ReproBoostZstd PROPERTY CXX_STANDARD 17) | |
endif() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#include <numeric> | |
#include <string> | |
#include <vector> | |
// disable exception support | |
#define BOOST_NO_UNREACHABLE_RETURN_DETECTION | |
#define BOOST_EXCEPTION_DISABLE | |
#define BOOST_NO_EXCEPTIONS | |
#include <boost/throw_exception.hpp> | |
#define BOOST_NO_UNREACHABLE_RETURN_DETECTION | |
// include headers that implement serialization support | |
#include <boost/serialization/split_member.hpp> | |
#include <boost/serialization/split_free.hpp> | |
#include <boost/serialization/utility.hpp> | |
#include <boost/serialization/export.hpp> | |
#include <boost/serialization/vector.hpp> | |
#include <boost/serialization/list.hpp> | |
#include <boost/serialization/map.hpp> | |
#include <boost/serialization/set.hpp> | |
#include <boost/serialization/nvp.hpp> | |
// include headers that define an input and output archive | |
#include <boost/archive/detail/common_oarchive.hpp> | |
#include <boost/archive/detail/common_iarchive.hpp> | |
// include headers that implement a archive in simple text and binary format or XML format | |
#if defined(_MSC_VER) | |
#pragma warning (push) | |
#pragma warning (disable : 4275) // non dll-interface class | |
#pragma warning (disable : 4715) // not all control paths return a value | |
#endif | |
#include <boost/archive/text_oarchive.hpp> | |
#include <boost/archive/text_iarchive.hpp> | |
#include <boost/archive/binary_oarchive.hpp> | |
#include <boost/archive/binary_iarchive.hpp> | |
// include headers that implement compressed serialization support | |
#include <boost/iostreams/filtering_streambuf.hpp> | |
#include <boost/iostreams/filter/zlib.hpp> | |
#if BOOST_VERSION >= 106900 | |
#include <boost/iostreams/filter/zstd.hpp> | |
#endif | |
#if defined(_MSC_VER) | |
#pragma warning (pop) | |
#endif | |
#if (BOOST_VERSION / 100000) > 1 || (BOOST_VERSION / 100 % 1000) > 72 | |
#include <boost/assert/source_location.hpp> | |
#endif | |
namespace boost { | |
void throw_exception(std::exception const & e) { | |
std::cout << "exception thrown: " << e.what() << std::endl; | |
exit(EXIT_FAILURE); | |
} | |
#if (BOOST_VERSION / 100000) > 1 || (BOOST_VERSION / 100 % 1000) > 72 | |
void throw_exception(std::exception const & e, boost::source_location const & loc) { | |
std::ostringstream ostr; ostr << loc; | |
std::cout << "exception thrown: " << ostr.str().c_str() << std::endl; | |
exit(EXIT_FAILURE); | |
} | |
#endif | |
} // namespace boost | |
enum ARCHIVE_TYPE { | |
ARCHIVE_TEXT = 0, | |
ARCHIVE_BINARY, | |
ARCHIVE_BINARY_ZIP, | |
ARCHIVE_BINARY_ZSTD, | |
ARCHIVE_LAST, | |
#if BOOST_VERSION >= 106900 | |
ARCHIVE_DEFAULT = ARCHIVE_BINARY_ZSTD | |
#else | |
ARCHIVE_DEFAULT = ARCHIVE_BINARY_ZIP | |
#endif | |
}; | |
// export the current state of the given reconstruction object | |
template <typename TYPE> | |
bool SerializeSave(const TYPE& obj, std::ofstream& fs, ARCHIVE_TYPE type, unsigned flags=boost::archive::no_header) | |
{ | |
// serialize out the current state | |
switch (type) { | |
case ARCHIVE_TEXT: { | |
boost::archive::text_oarchive ar(fs, flags); | |
ar << obj; | |
break; } | |
case ARCHIVE_BINARY: { | |
boost::archive::binary_oarchive ar(fs, flags); | |
ar << obj; | |
break; } | |
case ARCHIVE_BINARY_ZIP: { | |
namespace io = boost::iostreams; | |
io::filtering_streambuf<io::output> ffs; | |
ffs.push(io::zlib_compressor(io::zlib::best_speed)); | |
ffs.push(fs); | |
boost::archive::binary_oarchive ar(ffs, flags); | |
ar << obj; | |
break; } | |
#if BOOST_VERSION >= 106900 | |
case ARCHIVE_BINARY_ZSTD: { | |
namespace io = boost::iostreams; | |
io::filtering_streambuf<io::output> ffs; | |
ffs.push(io::zstd_compressor(io::zstd::best_speed)); | |
ffs.push(fs); | |
boost::archive::binary_oarchive ar(ffs, flags); | |
ar << obj; | |
break; } | |
#endif | |
default: | |
return false; | |
} | |
return true; | |
} // SerializeSave | |
template <typename TYPE> | |
bool SerializeSave(const TYPE& obj, const std::string& fileName, ARCHIVE_TYPE type, unsigned flags=boost::archive::no_header) | |
{ | |
// open the output stream | |
std::ofstream fs(fileName, std::ios::out | std::ios::binary); | |
if (!fs.is_open()) | |
return false; | |
// serialize out the current state | |
return SerializeSave(obj, fs, type, flags); | |
} // SerializeSave | |
// import the state to the given reconstruction object | |
template <typename TYPE> | |
bool SerializeLoad(TYPE& obj, std::ifstream& fs, ARCHIVE_TYPE type, unsigned flags=boost::archive::no_header) | |
{ | |
try { | |
// serialize in the saved state | |
switch (type) { | |
case ARCHIVE_TEXT: { | |
boost::archive::text_iarchive ar(fs, flags); | |
ar >> obj; | |
break; } | |
case ARCHIVE_BINARY: { | |
boost::archive::binary_iarchive ar(fs, flags); | |
ar >> obj; | |
break; } | |
case ARCHIVE_BINARY_ZIP: { | |
namespace io = boost::iostreams; | |
io::filtering_streambuf<io::input> ffs; | |
ffs.push(io::zlib_decompressor()); | |
ffs.push(fs); | |
boost::archive::binary_iarchive ar(ffs, flags); | |
ar >> obj; | |
break; } | |
#if BOOST_VERSION >= 106900 | |
case ARCHIVE_BINARY_ZSTD: { | |
namespace io = boost::iostreams; | |
io::filtering_streambuf<io::input> ffs; | |
ffs.push(io::zstd_decompressor()); | |
ffs.push(fs); | |
boost::archive::binary_iarchive ar(ffs, flags); | |
ar >> obj; | |
break; } | |
#endif | |
default: | |
return false; | |
} | |
} | |
catch (const std::exception& e) { | |
std::cout << "error: invalid stream " << e.what() << std::endl; | |
return false; | |
} | |
return true; | |
} // SerializeLoad | |
template <typename TYPE> | |
bool SerializeLoad(TYPE& obj, const std::string& fileName, ARCHIVE_TYPE type, unsigned flags=boost::archive::no_header) | |
{ | |
// open the input stream | |
std::ifstream fs(fileName, std::ios::in | std::ios::binary); | |
if (!fs.is_open()) | |
return false; | |
// serialize in the saved state | |
return SerializeLoad(obj, fs, type, flags); | |
} // SerializeLoad | |
struct Data { | |
std::vector<int> values; | |
float scale; | |
// implement BOOST serialization | |
template <class Archive> | |
void serialize(Archive& ar, const unsigned int /*version*/) { | |
ar & values; | |
ar & scale; | |
} | |
}; | |
int main() | |
{ | |
Data data; | |
data.scale = 2.3f; | |
data.values.resize(100); | |
std::iota(data.values.begin(), data.values.end(), 0); | |
const std::string fileName("data.bin"); | |
if (!SerializeSave(data, fileName, ARCHIVE_DEFAULT)) | |
return EXIT_FAILURE; | |
Data loadedData; | |
if (!SerializeLoad(loadedData, fileName, ARCHIVE_DEFAULT)) | |
return EXIT_FAILURE; | |
if (loadedData.scale != data.scale || loadedData.values != data.values) | |
return EXIT_FAILURE; | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment