Changed the serialization code for C-strings so that they don't save the null terminator

byte.  This makes their serialization format the same as the format for std::string.  I had
to revert the previous mod for this because it didn't work in visual studio.  This change
fixes that.  The code should still be able to read all previously serialized data correctly.
Moreover, any char arrays that aren't null terminated will still be read and written in
their entirety.
This commit is contained in:
Davis King 2014-07-08 21:50:50 -04:00
parent 06bf7e0e38
commit f3ce10594f
2 changed files with 78 additions and 32 deletions

View File

@ -1207,6 +1207,41 @@ namespace dlib
}
}
template <
size_t length
>
inline void serialize (
const char (&array)[length],
std::ostream& out
)
{
if (length != 0 && array[length-1] == '\0')
{
// If this is a null terminated string then don't serialize the trailing null.
// We do this so that the serialization format for C-strings is the same as
// std::string.
serialize(length-1, out);
out.write(array, length-1);
if (!out)
throw serialization_error("Error serializing a C-style string");
}
else
{
try
{
serialize(length,out);
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while serializing a C style array");
}
if (length != 0)
out.write(array, length);
if (!out)
throw serialization_error("Error serializing a C-style string");
}
}
// ----------------------------------------------------------------------------------------
template <
@ -1237,6 +1272,45 @@ namespace dlib
throw serialization_error("Error deserializing a C style array, lengths do not match");
}
template <
size_t length
>
inline void deserialize (
char (&array)[length],
std::istream& in
)
{
size_t size;
try
{
deserialize(size,in);
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while deserializing a C style array");
}
if (size == length)
{
in.read(array, size);
if (!in)
throw serialization_error("Error deserializing a C-style array");
}
else if (size+1 == length)
{
// In this case we are deserializing a C-style array so we need to add the null
// terminator.
in.read(array, size);
array[size] = '\0';
if (!in)
throw serialization_error("Error deserializing a C-style string");
}
else
{
throw serialization_error("Error deserializing a C style array, lengths do not match");
}
}
// ----------------------------------------------------------------------------------------
template <
@ -1281,17 +1355,6 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
inline void serialize(const char* item, std::ostream& out)
{
// We serialize literal strings the same way we serialize std::string, that is, we
// write the data but no trailing 0 byte.
const unsigned long length = strlen(item);
serialize(length, out);
out.write(item, length);
}
// ----------------------------------------------------------------------------------------
class proxy_serialize
@ -1313,24 +1376,6 @@ namespace dlib
return *this;
}
template <size_t length>
proxy_serialize& operator<<(const char (&item)[length])
{
// We serialize char arrays like we do all other arrays. That is, we write
// every element.
serialize(length, *fout);
fout->write(item, length);
return *this;
}
proxy_serialize& operator<<(const char* item)
{
// We serialize literal strings the same way we serialize std::string, that is,
// we write the data but no trailing 0 byte.
serialize(item, *fout);
return *this;
}
private:
shared_ptr<std::ofstream> fout;
};

View File

@ -953,14 +953,15 @@ namespace
buf[4] = 3;
buf[5] = 3;
dlib::serialize("ser_test_string.dat") << str1 << buf << "morestuff";
dlib::serialize("ser_test_string.dat") << str1 << buf << "morestuff" << "";
string str2, str3;
string str2, str3, str4;
char buf2[6];
memset(buf2,0,sizeof(buf2));
dlib::deserialize("ser_test_string.dat") >> str2 >> buf2 >> str3;
dlib::deserialize("ser_test_string.dat") >> str2 >> buf2 >> str3 >> str4;
DLIB_TEST(str2 == "stuff");
DLIB_TEST(str3 == "morestuff");
DLIB_TEST(str4 == "");
DLIB_TEST(buf2[0] == 0);
DLIB_TEST(buf2[1] == 1);
DLIB_TEST(buf2[2] == 2);