diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 733ae9a3c56060fb942eb9c06377a4f00d9f2fcb..d8aa740acd8b9fbc3f1e0e87e40af15e0c60f26a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,6 +69,12 @@ else(OpenCV_FOUND) message("[WARN] OpenCV not found. Related sources will NOT be built.") endif(OpenCV_FOUND) +# Cereal +FIND_PACKAGE(cereal QUIET) +IF(cereal_FOUND) + MESSAGE("cereal Library FOUND: cereal related sources will be built.") +ENDIF(cereal_FOUND) + # YAML with yaml-cpp INCLUDE (${PROJECT_SOURCE_DIR}/cmake_modules/FindYamlCpp.cmake) IF(YAMLCPP_FOUND) @@ -161,6 +167,11 @@ IF(OpenCV_FOUND) INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS}) ENDIF(OpenCV_FOUND) +# cereal +IF(cereal_FOUND) + INCLUDE_DIRECTORIES(${cereal_INCLUDE_DIRS}) +ENDIF(cereal_FOUND) + IF(Suitesparse_FOUND) INCLUDE_DIRECTORIES(${Suitesparse_INCLUDE_DIRS}) ENDIF(Suitesparse_FOUND) @@ -413,6 +424,10 @@ IF (OpenCV_FOUND) ) ENDIF(OpenCV_FOUND) +IF (cereal_FOUND) + ADD_SUBDIRECTORY(serialization/cereal) +ENDIF(cereal_FOUND) + IF (Suitesparse_FOUND) ADD_SUBDIRECTORY(solver) ENDIF(Suitesparse_FOUND) @@ -502,6 +517,8 @@ INSTALL(FILES ${HDRS_WRAPPER} DESTINATION include/iri-algorithms/wolf/ceres_wrapper) INSTALL(FILES ${HDRS_SOLVER} DESTINATION include/iri-algorithms/wolf/solver) +INSTALL(FILES ${HDRS_SERIALIZATION} + DESTINATION include/iri-algorithms/wolf/serialization) INSTALL(FILES "${CMAKE_SOURCE_DIR}/cmake_modules/Findwolf.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}") diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a853ba8ec5158727fcd4bfd9752d6de398c5aefa --- /dev/null +++ b/src/serialization/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(cereal) diff --git a/src/serialization/cereal/CMakeLists.txt b/src/serialization/cereal/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f2c1ee7a067ab1e82692c2c447ee1e97000c3104 --- /dev/null +++ b/src/serialization/cereal/CMakeLists.txt @@ -0,0 +1,7 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +SET(HDRS_SERIALIZATION ${HDRS_SERIALIZATION} + ${CMAKE_CURRENT_SOURCE_DIR}/archives.h + ${CMAKE_CURRENT_SOURCE_DIR}/io.h + + PARENT_SCOPE) diff --git a/src/serialization/cereal/archives.h b/src/serialization/cereal/archives.h new file mode 100644 index 0000000000000000000000000000000000000000..d8c16fd180ef04049ceedaf268fa33782790d27a --- /dev/null +++ b/src/serialization/cereal/archives.h @@ -0,0 +1,9 @@ +#ifndef _WOLF_IO_CEREAL_ARCHIVE_H_ +#define _WOLF_IO_CEREAL_ARCHIVE_H_ + +#include <cereal/archives/binary.hpp> +#include <cereal/archives/json.hpp> +#include <cereal/archives/portable_binary.hpp> +#include <cereal/archives/xml.hpp> + +#endif /* _WOLF_IO_CEREAL_ARCHIVE_H_ */ diff --git a/src/serialization/cereal/io.h b/src/serialization/cereal/io.h new file mode 100644 index 0000000000000000000000000000000000000000..afd32843878e43a66674970a69df37dbf6429fe2 --- /dev/null +++ b/src/serialization/cereal/io.h @@ -0,0 +1,216 @@ +#ifndef _WOLF_SERIALIZATION_CEREAL_IO_H_ +#define _WOLF_SERIALIZATION_CEREAL_IO_H_ + +#include <stdexcept> +#include "archives.h" + +//#include <cereal/types/tuple.hpp> + +namespace wolf { +namespace serialization { + +inline std::string extension(const std::string& file) +{ + const std::size_t p = file.find_last_of("."); + return (p != std::string::npos) ? file.substr(p) : ""; +} + +//struct Extensions +//{ +// constexpr static const char* bin = ".bin"; +// constexpr static const char* json = ".json"; +// constexpr static const char* xml = ".xml"; + +// constexpr static const char* fall_back = json; +//}; + +//enum class Extensions2 : std::size_t +//{ +// BIN = 0, +//// CBIN, +// JSON, +//// TEXT, +// XML, +//}; + +//template <char... Chars> +//struct constexp_str +//{ +// using type = constexp_str<Chars...>; + +// virtual ~constexp_str() = default; + +// constexpr static const char value[sizeof...(Chars)+1] = {Chars..., '\0'}; + +// constexpr static std::size_t size() { return sizeof...(Chars); } + +// constexpr static const char* c_str() { return &value[0]; } + +//// constexpr static bool comp(const std::string& s) { return s == value; } + +// /*constexpr*/ bool operator == (const std::string& s) { return s == value; } + +// constexpr /*static*/ operator const char* () { return c_str(); } +// constexpr /*static*/ operator std::string& () { return c_str(); } +//}; + +struct Extensions +{ +// template <char... Chars> +// struct EXT : constexp_str<Chars...> +// { +// // +// }; + +// struct BIN : EXT<'.','b','i','n'> { }; +// struct XML : EXT<'.','x','m','l'> { }; +// struct JSON : EXT<'.','j','s','o','n'> { }; + + struct EXT { virtual ~EXT() = default; }; + + struct BIN : EXT + { + constexpr static const char* value = ".bin"; + bool operator == (const std::string& s) { return value == s; } + }; + + struct XML : EXT + { + constexpr static const char* value = ".xml"; + bool operator == (const std::string& s) { return value == s; } + }; + + struct JSON : EXT + { + constexpr static const char* value = ".json"; + bool operator == (const std::string& s) { return value == s; } + }; +}; + +template <typename Ar, typename S, typename T, typename... Args> +void serialize(S& stream, T&& object, Args&&... args) +{ + Ar archive(stream); + + archive( cereal::make_nvp("object", std::forward<T>(object)) ); + archive( cereal::make_nvp("object", std::forward<Args>(args))... ); +} + +template <typename Ar, typename S, typename T> +void serialize(S& stream, T&& object) +{ + Ar archive(stream); + archive( cereal::make_nvp("object", std::forward<T>(object)) ); +} + +template <typename EXT, typename InAr, typename OutAr> +struct Serializer +{ + template <typename S, typename... T> + static void serialize_in(S& stream, T&... object) + { + serialize<InAr>(stream, object...); + } + + template <typename S, typename... T> + static void serialize_out(S& stream, T&&... object) + { + serialize<OutAr>(stream, std::forward<T>(object)...); + } + + template <typename... T> + static void save(std::string filename, T&&... o) + { + const std::string ext = serialization::extension(filename); + + if (ext != EXT::value) filename += EXT::value; + + std::ofstream os(filename); + serialize_out(os, std::forward<T>(o)...); + } + + template <typename... T> + static void load(std::string filename, T&... o) + { + const std::string ext = serialization::extension(filename); + + if (ext != EXT::value) filename += EXT::value; + + std::ifstream is(filename); + serialize_in(is, o...); + } +}; + +using SerializerBin = Serializer<Extensions::BIN, + cereal::BinaryInputArchive, + cereal::BinaryOutputArchive>; + +using SerializerXML = Serializer<Extensions::XML, + cereal::XMLInputArchive, + cereal::XMLOutputArchive>; + +using SerializerJSON = Serializer<Extensions::JSON, + cereal::JSONInputArchive, + cereal::JSONOutputArchive>; + + +} /* namespace serialization */ + +template <typename... T> +void save(const std::string& filename, T&&... o) +throw(std::runtime_error) +{ + const std::string ext = serialization::extension(filename); + + if (ext == serialization::Extensions::BIN::value) + { + serialization::SerializerBin::save(filename, std::forward<T>(o)...); + } + else if (ext == serialization::Extensions::JSON::value) + { + serialization::SerializerJSON::save(filename, std::forward<T>(o)...); + } + else if (ext == serialization::Extensions::XML::value) + { + serialization::SerializerXML::save(filename, std::forward<T>(o)...); + } + else if (ext == "") // falback is json + { + serialization::SerializerJSON::save(filename, std::forward<T>(o)...); + } + else + { + throw std::runtime_error("Unknown file extension : " + filename); + } +} + +template <typename... T> +void load(const std::string& filename, T&... o) +{ + const std::string ext = serialization::extension(filename); + + if (ext == serialization::Extensions::BIN::value) + { + serialization::SerializerBin::load(filename, o...); + } + else if (ext == serialization::Extensions::XML::value) + { + serialization::SerializerXML::load(filename, o...); + } + else if (ext == serialization::Extensions::JSON::value) + { + serialization::SerializerJSON::load(filename, o...); + } + else if (ext == "") // falback is json + { + serialization::SerializerJSON::load(filename, o...); + } + else + { + throw std::runtime_error("Unknown file extension : " + filename); + } +} + +} /* namespace wolf */ + +#endif /* _WOLF_SERIALIZATION_CEREAL_IO_H_ */