Skip to content

Instantly share code, notes, and snippets.

@cdcseacave
Created November 23, 2022 08:35
Show Gist options
  • Save cdcseacave/dd8c7bd64f6559cf10d3b0143a42743a to your computer and use it in GitHub Desktop.
Save cdcseacave/dd8c7bd64f6559cf10d3b0143a42743a to your computer and use it in GitHub Desktop.
Example using Boost serialization with ZSTD or ZIP compression
# 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()
#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