"git@developer.sourcefind.cn:OpenDAS/dlib.git" did not exist on "ec342e39bdf7721f84ca4adaf1046c1621438250"
Unverified Commit ab346ddf authored by pfeatherstone's avatar pfeatherstone Committed by GitHub
Browse files

Extended proxy_(de)serialize objects to work with stringstream, ostringstream,...


Extended proxy_(de)serialize objects to work with stringstream, ostringstream, istringstream and vector<char> (#2181)

* [DLIB] extended proxy objects to work with strinstream, istringstream, ostringstream and vector<char>

* [DLIB]  - use std::istream and std::ostream instead of std::istringstream, std::ostringstream and std::stringstream.
		- put back the filename member variable for better error messages

* [DLIB]  - review requirement
Co-authored-by: default avatarpf <pf@pf-ubuntu-dev>
parent fa818b9a
......@@ -203,6 +203,7 @@
#include "unicode.h"
#include "byte_orderer.h"
#include "float_details.h"
#include "vectorstream.h"
namespace dlib
{
......@@ -1583,47 +1584,73 @@ namespace dlib
// ----------------------------------------------------------------------------------------
class proxy_serialize
class proxy_serialize
{
public:
explicit proxy_serialize (
const std::string& filename
)
) : fout_optional_owning_ptr(new std::ofstream(filename.c_str(), std::ios::binary)),
fout(*fout_optional_owning_ptr)
{
fout.reset(new std::ofstream(filename.c_str(), std::ios::binary));
if (!(*fout))
if (!fout)
throw serialization_error("Unable to open " + filename + " for writing.");
}
explicit proxy_serialize (
std::vector<char>& buf
) : fout_optional_owning_ptr(new vectorstream(buf)),
fout(*fout_optional_owning_ptr)
{
}
explicit proxy_serialize (
std::ostream& ss
) : fout_optional_owning_ptr(nullptr),
fout(ss)
{}
template <typename T>
inline proxy_serialize& operator<<(const T& item)
{
serialize(item, *fout);
serialize(item, fout);
return *this;
}
private:
std::shared_ptr<std::ofstream> fout;
std::unique_ptr<std::ostream> fout_optional_owning_ptr;
std::ostream& fout;
};
class proxy_deserialize
class proxy_deserialize
{
public:
explicit proxy_deserialize (
const std::string& filename
) : filename(filename)
const std::string& filename_
) : filename(filename_),
fin_optional_owning_ptr(new std::ifstream(filename.c_str(), std::ios::binary)),
fin(*fin_optional_owning_ptr)
{
fin.reset(new std::ifstream(filename.c_str(), std::ios::binary));
if (!(*fin))
if (!fin)
throw serialization_error("Unable to open " + filename + " for reading.");
// read the file header into a buffer and then seek back to the start of the
// file.
fin->read(file_header,4);
fin->clear();
fin->seekg(0);
init();
}
explicit proxy_deserialize (
std::vector<char>& buf
) : fin_optional_owning_ptr(new vectorstream(buf)),
fin(*fin_optional_owning_ptr)
{
init();
}
explicit proxy_deserialize (
std::istream& ss
) : fin_optional_owning_ptr(nullptr),
fin(ss)
{
init();
}
template <typename T>
inline proxy_deserialize& operator>>(T& item)
{
......@@ -1635,16 +1662,28 @@ namespace dlib
{
return doit(std::move(item));
}
private:
void init()
{
// read the file header into a buffer and then seek back to the start of the
// file.
fin.read(file_header,4);
fin.clear();
fin.seekg(0);
}
private:
template <typename T>
inline proxy_deserialize& doit(T&& item)
{
try
{
if (fin->peek() == EOF)
throw serialization_error("No more objects were in the file!");
deserialize(std::forward<T>(item), *fin);
if (fin.peek() == EOF)
throw serialization_error("No more objects were in the stream!");
deserialize(std::forward<T>(item), fin);
}
catch (serialization_error& e)
{
......@@ -1652,28 +1691,27 @@ namespace dlib
if (looks_like_a_compressed_file())
suffix = "\n *** THIS LOOKS LIKE A COMPRESSED FILE. DID YOU FORGET TO DECOMPRESS IT? *** \n";
const std::string stream_description = filename.empty() ? "stream" : "file '" + filename + "'";
if (objects_read == 0)
{
throw serialization_error("An error occurred while trying to read the first"
" object from the file " + filename + ".\nERROR: " + e.info + "\n" + suffix);
" object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix);
}
else if (objects_read == 1)
{
throw serialization_error("An error occurred while trying to read the second"
" object from the file " + filename +
".\nERROR: " + e.info + "\n" + suffix);
" object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix);
}
else if (objects_read == 2)
{
throw serialization_error("An error occurred while trying to read the third"
" object from the file " + filename +
".\nERROR: " + e.info + "\n" + suffix);
" object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix);
}
else
{
throw serialization_error("An error occurred while trying to read the " +
std::to_string(objects_read+1) + "th object from the file " + filename +
".\nERROR: " + e.info + "\n" + suffix);
std::to_string(objects_read+1) + "th object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix);
}
}
++objects_read;
......@@ -1681,8 +1719,9 @@ namespace dlib
}
int objects_read = 0;
std::string filename;
std::shared_ptr<std::ifstream> fin;
const std::string filename = "";
std::unique_ptr<std::istream> fin_optional_owning_ptr;
std::istream& fin;
// We don't need to look at the file header. However, it's here because people
// keep posting questions to the dlib forums asking why they get file load errors.
......@@ -1708,8 +1747,16 @@ namespace dlib
inline proxy_serialize serialize(const std::string& filename)
{ return proxy_serialize(filename); }
inline proxy_serialize serialize(std::ostream& ss)
{ return proxy_serialize(ss); }
inline proxy_serialize serialize(std::vector<char>& buf)
{ return proxy_serialize(buf); }
inline proxy_deserialize deserialize(const std::string& filename)
{ return proxy_deserialize(filename); }
inline proxy_deserialize deserialize(std::istream& ss)
{ return proxy_deserialize(ss); }
inline proxy_deserialize deserialize(std::vector<char>& buf)
{ return proxy_deserialize(buf); }
// ----------------------------------------------------------------------------------------
......
......@@ -1054,7 +1054,7 @@ namespace
}
}
void test_macros()
void test_macros_and_serializers()
{
my_custom_type t1, t2, t3, t4;
t1.a = 1;
......@@ -1069,12 +1069,45 @@ namespace
v1.v.push_back(t1);
v1.v.push_back(t2);
dlib::serialize("serialization_test_macros.dat") << t1 << t2 << v1;
dlib::deserialize("serialization_test_macros.dat") >> t3 >> t4 >> v2;
{
dlib::serialize("serialization_test_macros.dat") << t1 << t2 << v1;
dlib::deserialize("serialization_test_macros.dat") >> t3 >> t4 >> v2;
DLIB_TEST(t1 == t3);
DLIB_TEST(t2 == t4);
DLIB_TEST(v1 == v2);
}
{
std::stringstream ss;
dlib::serialize(ss) << t1 << t2 << v1;
dlib::deserialize(ss) >> t3 >> t4 >> v2;
DLIB_TEST(t1 == t3);
DLIB_TEST(t2 == t4);
DLIB_TEST(v1 == v2);
}
{
std::ostringstream sout;
dlib::serialize(sout) << t1 << t2 << v1;
std::istringstream sin(sout.str());
dlib::deserialize(sin) >> t3 >> t4 >> v2;
DLIB_TEST(t1 == t3);
DLIB_TEST(t2 == t4);
DLIB_TEST(v1 == v2);
}
{
std::vector<char> buf;
dlib::serialize(buf) << t1 << t2 << v1;
dlib::deserialize(buf) >> t3 >> t4 >> v2;
DLIB_TEST(t1 == t3);
DLIB_TEST(t2 == t4);
DLIB_TEST(v1 == v2);
DLIB_TEST(t1 == t3);
DLIB_TEST(t2 == t4);
DLIB_TEST(v1 == v2);
}
}
// ----------------------------------------------------------------------------------------
......@@ -1105,7 +1138,7 @@ namespace
test_array2d_and_matrix_serialization();
test_strings();
test_std_array();
test_macros();
test_macros_and_serializers();
}
} a;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment