diff --git a/gtsam/base/serialization.h b/gtsam/base/serialization.h index e475465de..f589ecc5e 100644 --- a/gtsam/base/serialization.h +++ b/gtsam/base/serialization.h @@ -42,123 +42,218 @@ namespace gtsam { -// Serialization directly to strings in compressed format -template -std::string serialize(const T& input) { - std::ostringstream out_archive_stream; +/** @name Standard serialization + * Serialization in default compressed format + */ +///@{ +/// serializes to a stream +template +void serializeToStream(const T& input, std::ostream& out_archive_stream) { boost::archive::text_oarchive out_archive(out_archive_stream); out_archive << input; - return out_archive_stream.str(); } -template -void deserialize(const std::string& serialized, T& output) { - std::istringstream in_archive_stream(serialized); +/// deserializes from a stream +template +void deserializeFromStream(std::istream& in_archive_stream, T& output) { boost::archive::text_iarchive in_archive(in_archive_stream); in_archive >> output; } -template +/// serializes to a string +template +std::string serializeToString(const T& input) { + std::ostringstream out_archive_stream; + serializeToStream(input, out_archive_stream); + return out_archive_stream.str(); +} + +/// deserializes from a string +template +void deserializeFromString(const std::string& serialized, T& output) { + std::istringstream in_archive_stream(serialized); + deserializeFromStream(in_archive_stream, output); +} + +/// serializes to a file +template bool serializeToFile(const T& input, const std::string& filename) { std::ofstream out_archive_stream(filename.c_str()); - if (!out_archive_stream.is_open()) - return false; - boost::archive::text_oarchive out_archive(out_archive_stream); - out_archive << input; + if (!out_archive_stream.is_open()) return false; + serializeToStream(input, out_archive_stream); out_archive_stream.close(); return true; } -template +/// deserializes from a file +template bool deserializeFromFile(const std::string& filename, T& output) { std::ifstream in_archive_stream(filename.c_str()); - if (!in_archive_stream.is_open()) - return false; - boost::archive::text_iarchive in_archive(in_archive_stream); - in_archive >> output; + if (!in_archive_stream.is_open()) return false; + deserializeFromStream(in_archive_stream, output); in_archive_stream.close(); return true; } -// Serialization to XML format with named structures -template -std::string serializeXML(const T& input, const std::string& name="data") { - std::ostringstream out_archive_stream; - // braces to flush out_archive as it goes out of scope before taking str() - // fixes crash with boost 1.66-1.68 - // see https://github.com/boostorg/serialization/issues/82 - { - boost::archive::xml_oarchive out_archive(out_archive_stream); - out_archive << boost::serialization::make_nvp(name.c_str(), input); - } - return out_archive_stream.str(); +/// serializes to a string +template +std::string serialize(const T& input) { + return serializeToString(input); } -template -void deserializeXML(const std::string& serialized, T& output, const std::string& name="data") { - std::istringstream in_archive_stream(serialized); - boost::archive::xml_iarchive in_archive(in_archive_stream); - in_archive >> boost::serialization::make_nvp(name.c_str(), output); +/// deserializes from a string +template +void deserialize(const std::string& serialized, T& output) { + deserializeFromString(serialized, output); } +///@} -template -bool serializeToXMLFile(const T& input, const std::string& filename, const std::string& name="data") { - std::ofstream out_archive_stream(filename.c_str()); - if (!out_archive_stream.is_open()) - return false; +/** @name XML Serialization + * Serialization to XML format with named structures + */ +///@{ +/// serializes to a stream in XML +template +void serializeToXMLStream(const T& input, std::ostream& out_archive_stream, + const std::string& name = "data") { boost::archive::xml_oarchive out_archive(out_archive_stream); - out_archive << boost::serialization::make_nvp(name.c_str(), input);; - out_archive_stream.close(); - return true; + out_archive << boost::serialization::make_nvp(name.c_str(), input); } -template -bool deserializeFromXMLFile(const std::string& filename, T& output, const std::string& name="data") { - std::ifstream in_archive_stream(filename.c_str()); - if (!in_archive_stream.is_open()) - return false; +/// deserializes from a stream in XML +template +void deserializeFromXMLStream(std::istream& in_archive_stream, T& output, + const std::string& name = "data") { boost::archive::xml_iarchive in_archive(in_archive_stream); in_archive >> boost::serialization::make_nvp(name.c_str(), output); - in_archive_stream.close(); - return true; } -// Serialization to binary format with named structures -template -std::string serializeBinary(const T& input, const std::string& name="data") { +/// serializes to a string in XML +template +std::string serializeToXMLString(const T& input, + const std::string& name = "data") { std::ostringstream out_archive_stream; - boost::archive::binary_oarchive out_archive(out_archive_stream); - out_archive << boost::serialization::make_nvp(name.c_str(), input); + serializeToXMLStream(input, out_archive_stream, name); return out_archive_stream.str(); } -template -void deserializeBinary(const std::string& serialized, T& output, const std::string& name="data") { +/// deserializes from a string in XML +template +void deserializeFromXMLString(const std::string& serialized, T& output, + const std::string& name = "data") { std::istringstream in_archive_stream(serialized); - boost::archive::binary_iarchive in_archive(in_archive_stream); - in_archive >> boost::serialization::make_nvp(name.c_str(), output); + deserializeFromXMLStream(in_archive_stream, output, name); } -template -bool serializeToBinaryFile(const T& input, const std::string& filename, const std::string& name="data") { +/// serializes to an XML file +template +bool serializeToXMLFile(const T& input, const std::string& filename, + const std::string& name = "data") { std::ofstream out_archive_stream(filename.c_str()); - if (!out_archive_stream.is_open()) - return false; - boost::archive::binary_oarchive out_archive(out_archive_stream); - out_archive << boost::serialization::make_nvp(name.c_str(), input); + if (!out_archive_stream.is_open()) return false; + serializeToXMLStream(input, out_archive_stream, name); out_archive_stream.close(); return true; } -template -bool deserializeFromBinaryFile(const std::string& filename, T& output, const std::string& name="data") { +/// deserializes from an XML file +template +bool deserializeFromXMLFile(const std::string& filename, T& output, + const std::string& name = "data") { std::ifstream in_archive_stream(filename.c_str()); - if (!in_archive_stream.is_open()) - return false; - boost::archive::binary_iarchive in_archive(in_archive_stream); - in_archive >> boost::serialization::make_nvp(name.c_str(), output); + if (!in_archive_stream.is_open()) return false; + deserializeFromXMLStream(in_archive_stream, output, name); in_archive_stream.close(); return true; } -} // \namespace gtsam +/// serializes to a string in XML +template +std::string serializeXML(const T& input, + const std::string& name = "data") { + return serializeToXMLString(input, name); +} + +/// deserializes from a string in XML +template +void deserializeXML(const std::string& serialized, T& output, + const std::string& name = "data") { + deserializeFromXMLString(serialized, output, name); +} +///@} + +/** @name Binary Serialization + * Serialization to binary format with named structures + */ +///@{ +/// serializes to a stream in binary +template +void serializeToBinaryStream(const T& input, std::ostream& out_archive_stream, + const std::string& name = "data") { + boost::archive::binary_oarchive out_archive(out_archive_stream); + out_archive << boost::serialization::make_nvp(name.c_str(), input); +} + +/// deserializes from a stream in binary +template +void deserializeFromBinaryStream(std::istream& in_archive_stream, T& output, + const std::string& name = "data") { + boost::archive::binary_iarchive in_archive(in_archive_stream); + in_archive >> boost::serialization::make_nvp(name.c_str(), output); +} + +/// serializes to a string in binary +template +std::string serializeToBinaryString(const T& input, + const std::string& name = "data") { + std::ostringstream out_archive_stream; + serializeToBinaryStream(input, out_archive_stream, name); + return out_archive_stream.str(); +} + +/// deserializes from a string in binary +template +void deserializeFromBinaryString(const std::string& serialized, T& output, + const std::string& name = "data") { + std::istringstream in_archive_stream(serialized); + deserializeFromBinaryStream(in_archive_stream, output, name); +} + +/// serializes to a binary file +template +bool serializeToBinaryFile(const T& input, const std::string& filename, + const std::string& name = "data") { + std::ofstream out_archive_stream(filename.c_str()); + if (!out_archive_stream.is_open()) return false; + serializeToBinaryStream(input, out_archive_stream, name); + out_archive_stream.close(); + return true; +} + +/// deserializes from a binary file +template +bool deserializeFromBinaryFile(const std::string& filename, T& output, + const std::string& name = "data") { + std::ifstream in_archive_stream(filename.c_str()); + if (!in_archive_stream.is_open()) return false; + deserializeFromBinaryStream(in_archive_stream, output, name); + in_archive_stream.close(); + return true; +} + +/// serializes to a string in binary +template +std::string serializeBinary(const T& input, + const std::string& name = "data") { + return serializeToBinaryString(input, name); +} + +/// deserializes from a string in binary +template +void deserializeBinary(const std::string& serialized, T& output, + const std::string& name = "data") { + deserializeFromBinaryString(serialized, output, name); +} +///@} + +} // namespace gtsam diff --git a/gtsam/base/serializationTestHelpers.h b/gtsam/base/serializationTestHelpers.h index 06b3462e9..5994a5e51 100644 --- a/gtsam/base/serializationTestHelpers.h +++ b/gtsam/base/serializationTestHelpers.h @@ -26,6 +26,7 @@ #include #include +#include // whether to print the serialized text to stdout @@ -40,22 +41,37 @@ T create() { return T(); } +// Creates or empties a folder in the build folder and returns the relative path +boost::filesystem::path resetFilesystem( + boost::filesystem::path folder = "actual") { + boost::filesystem::remove_all(folder); + boost::filesystem::create_directory(folder); + return folder; +} + // Templated round-trip serialization template void roundtrip(const T& input, T& output) { - // Serialize std::string serialized = serialize(input); if (verbose) std::cout << serialized << std::endl << std::endl; - deserialize(serialized, output); } -// This version requires equality operator +// Templated round-trip serialization using a file +template +void roundtripFile(const T& input, T& output) { + boost::filesystem::path path = resetFilesystem()/"graph.dat"; + serializeToFile(input, path.string()); + deserializeFromFile(path.string(), output); +} + +// This version requires equality operator and uses string and file round-trips template bool equality(const T& input = T()) { - T output = create(); + T output = create(), outputf = create(); roundtrip(input,output); - return input==output; + roundtripFile(input,outputf); + return (input==output) && (input==outputf); } // This version requires Testable @@ -77,20 +93,26 @@ bool equalsDereferenced(const T& input) { // Templated round-trip serialization using XML template void roundtripXML(const T& input, T& output) { - // Serialize std::string serialized = serializeXML(input); if (verbose) std::cout << serialized << std::endl << std::endl; - - // De-serialize deserializeXML(serialized, output); } +// Templated round-trip serialization using XML File +template +void roundtripXMLFile(const T& input, T& output) { + boost::filesystem::path path = resetFilesystem()/"graph.xml"; + serializeToXMLFile(input, path.string()); + deserializeFromXMLFile(path.string(), output); +} + // This version requires equality operator template bool equalityXML(const T& input = T()) { - T output = create(); + T output = create(), outputf = create(); roundtripXML(input,output); - return input==output; + roundtripXMLFile(input,outputf); + return (input==output) && (input==outputf); } // This version requires Testable @@ -112,20 +134,26 @@ bool equalsDereferencedXML(const T& input = T()) { // Templated round-trip serialization using XML template void roundtripBinary(const T& input, T& output) { - // Serialize std::string serialized = serializeBinary(input); if (verbose) std::cout << serialized << std::endl << std::endl; - - // De-serialize deserializeBinary(serialized, output); } +// Templated round-trip serialization using Binary file +template +void roundtripBinaryFile(const T& input, T& output) { + boost::filesystem::path path = resetFilesystem()/"graph.bin"; + serializeToBinaryFile(input, path.string()); + deserializeFromBinaryFile(path.string(), output); +} + // This version requires equality operator template bool equalityBinary(const T& input = T()) { - T output = create(); + T output = create(), outputf = create(); roundtripBinary(input,output); - return input==output; + roundtripBinaryFile(input,outputf); + return (input==output) && (input==outputf); } // This version requires Testable