summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/serialize.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/serialize.h')
-rw-r--r--ml/dlib/dlib/serialize.h1779
1 files changed, 0 insertions, 1779 deletions
diff --git a/ml/dlib/dlib/serialize.h b/ml/dlib/dlib/serialize.h
deleted file mode 100644
index f21bdaaff..000000000
--- a/ml/dlib/dlib/serialize.h
+++ /dev/null
@@ -1,1779 +0,0 @@
-// Copyright (C) 2005 Davis E. King (davis@dlib.net)
-// License: Boost Software License See LICENSE.txt for the full license.
-#ifndef DLIB_SERIALIZe_
-#define DLIB_SERIALIZe_
-
-/*!
- There are two global functions in the dlib namespace that provide serialization and
- deserialization support. Their signatures and specifications are as follows:
-
- void serialize (
- const serializable_type& item,
- std::ostream& out
- );
- /!*
- ensures
- - writes the state of item to the output stream out
- - if (serializable_type implements the enumerable interface) then
- - item.at_start() == true
- throws
- - serialization_error
- This exception is thrown if there is some problem which prevents
- us from successfully writing item to the output stream.
- - any other exception
- *!/
-
- void deserialize (
- serializable_type& item,
- std::istream& in
- );
- /!*
- ensures
- - #item == a deserialized copy of the serializable_type that was
- in the input stream in.
- - Reads all the bytes associated with the serialized serializable_type
- contained inside the input stream and no more. This means you
- can serialize multiple objects to an output stream and then read
- them all back in, one after another, using deserialize().
- - if (serializable_type implements the enumerable interface) then
- - item.at_start() == true
- throws
- - serialization_error
- This exception is thrown if there is some problem which prevents
- us from successfully deserializing item from the input stream.
- If this exception is thrown then item will have an initial value
- for its type.
- - any other exception
- *!/
-
- For convenience, you can also serialize to a file using this syntax:
- serialize("your_file.dat") << some_object << another_object;
-
- That overwrites the contents of your_file.dat with the serialized data from some_object
- and another_object. Then to recall the objects from the file you can do:
- deserialize("your_file.dat") >> some_object >> another_object;
-
- Finally, you can chain as many objects together using the << and >> operators as you
- like.
-
-
- This file provides serialization support to the following object types:
- - The C++ base types (NOT including pointer types)
- - std::string
- - std::wstring
- - std::vector
- - std::array
- - std::deque
- - std::map
- - std::set
- - std::pair
- - std::complex
- - dlib::uint64
- - dlib::int64
- - float_details
- - enumerable<T> where T is a serializable type
- - map_pair<D,R> where D and R are both serializable types.
- - C style arrays of serializable types
- - Google protocol buffer objects.
-
- This file provides deserialization support to the following object types:
- - The C++ base types (NOT including pointer types)
- - std::string
- - std::wstring
- - std::vector
- - std::array
- - std::deque
- - std::map
- - std::set
- - std::pair
- - std::complex
- - dlib::uint64
- - dlib::int64
- - float_details
- - C style arrays of serializable types
- - Google protocol buffer objects.
-
- Support for deserialization of objects which implement the enumerable or
- map_pair interfaces is the responsibility of those objects.
-
- Note that you can deserialize an integer value to any integral type (except for a
- char type) if its value will fit into the target integer type. I.e. the types
- short, int, long, unsigned short, unsigned int, unsigned long, and dlib::uint64
- can all receive serialized data from each other so long as the actual serialized
- value fits within the receiving integral type's range.
-
- Also note that for any container to be serializable the type of object it contains
- must be serializable.
-
- FILE STREAMS
- If you are serializing to and from file streams it is important to
- remember to set the file streams to binary mode using the std::ios::binary
- flag.
-
-
- INTEGRAL SERIALIZATION FORMAT
- All C++ integral types (except the char types) are serialized to the following
- format:
- The first byte is a control byte. It tells you if the serialized number is
- positive or negative and also tells you how many of the following bytes are
- part of the number. The absolute value of the number is stored in little
- endian byte order and follows the control byte.
-
- The control byte:
- The high order bit of the control byte is a flag that tells you if the
- encoded number is negative or not. It is set to 1 when the number is
- negative and 0 otherwise.
- The 4 low order bits of the control byte represent an unsigned number
- and tells you how many of the following bytes are part of the encoded
- number.
-
- bool SERIALIZATION FORMAT
- A bool value is serialized as the single byte character '1' or '0' in ASCII.
- Where '1' indicates true and '0' indicates false.
-
- FLOATING POINT SERIALIZATION FORMAT
- To serialize a floating point value we convert it into a float_details object and
- then serialize the exponent and mantissa values using dlib's integral serialization
- format. Therefore, the output is first the exponent and then the mantissa. Note that
- the mantissa is a signed integer (i.e. there is not a separate sign bit).
-!*/
-
-
-#include "algs.h"
-#include "assert.h"
-#include <iomanip>
-#include <cstddef>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <vector>
-#include <array>
-#include <deque>
-#include <complex>
-#include <map>
-#include <memory>
-#include <set>
-#include <limits>
-#include <type_traits>
-#include <utility>
-#include "uintn.h"
-#include "interfaces/enumerable.h"
-#include "interfaces/map_pair.h"
-#include "enable_if.h"
-#include "unicode.h"
-#include "byte_orderer.h"
-#include "float_details.h"
-
-namespace dlib
-{
-
-// ----------------------------------------------------------------------------------------
-
- class serialization_error : public error
- {
- /*!
- WHAT THIS OBJECT REPRESENTS
- This is the exception object. It is thrown if serialization or
- deserialization fails.
- !*/
-
- public:
- serialization_error(const std::string& e):error(e) {}
- };
-
-
- void check_serialized_version(
- const std::string& expected_version,
- std::istream& in
- );
- /*!
- ensures
- - Deserializes a string from in and if it doesn't match expected_version we
- throw serialization_error.
- !*/
-
-// ----------------------------------------------------------------------------------------
-
- /*!A ramdump information !*/
- template <typename T>
- struct ramdump_t
- {
- /*!
- WHAT THIS OBJECT REPRESENTS
- This is a type decoration used to indicate that serialization should be
- done by simply dumping the memory of some object to disk as fast as
- possible without any sort of conversions. This means that the data written
- will be "non-portable" in the sense that the format output by a RAM dump
- may depend on things like the endianness of your CPU or settings of certain
- compiler switches.
-
- You use this object like this:
- serialize("yourfile.dat") << ramdump(yourobject);
- deserialize("yourfile.dat") >> ramdump(yourobject);
- or
- serialize(ramdump(yourobject), out);
- deserialize(ramdump(yourobject), in);
-
- Also, not all objects have a ramdump mode. If you try to use ramdump on an
- object that does not define a serialization dump for ramdump you will get a
- compiler error.
- !*/
- ramdump_t(T& item_) : item(item_) {}
- T& item;
- };
-
- // This function just makes a ramdump that wraps an object.
- template <typename T>
- ramdump_t<typename std::remove_reference<T>::type> ramdump(T&& item)
- {
- return ramdump_t<typename std::remove_reference<T>::type>(item);
- }
-
-
- template <
- typename T
- >
- void serialize (
- const ramdump_t<const T>& item_,
- std::ostream& out
- )
- {
- // Move the const from inside the ramdump_t template to outside so we can bind
- // against a serialize() call that takes just a const ramdump_t<T>. Doing this
- // saves you from needing to write multiple overloads of serialize() to handle
- // these different const placement cases.
- const auto temp = ramdump(const_cast<T&>(item_.item));
- serialize(temp, out);
- }
-
-// ----------------------------------------------------------------------------------------
-
- namespace ser_helper
- {
-
- template <
- typename T
- >
- typename enable_if_c<std::numeric_limits<T>::is_signed,bool>::type pack_int (
- T item,
- std::ostream& out
- )
- /*!
- requires
- - T is a signed integral type
- ensures
- - if (no problems occur serializing item) then
- - writes item to out
- - returns false
- - else
- - returns true
- !*/
- {
- COMPILE_TIME_ASSERT(sizeof(T) <= 8);
- unsigned char buf[9];
- unsigned char size = sizeof(T);
- unsigned char neg;
- if (item < 0)
- {
- neg = 0x80;
- item *= -1;
- }
- else
- {
- neg = 0;
- }
-
- for (unsigned char i = 1; i <= sizeof(T); ++i)
- {
- buf[i] = static_cast<unsigned char>(item&0xFF);
- item >>= 8;
- if (item == 0) { size = i; break; }
- }
-
- std::streambuf* sbuf = out.rdbuf();
- buf[0] = size|neg;
- if (sbuf->sputn(reinterpret_cast<char*>(buf),size+1) != size+1)
- {
- out.setstate(std::ios::eofbit | std::ios::badbit);
- return true;
- }
-
- return false;
- }
-
- // ------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- typename enable_if_c<std::numeric_limits<T>::is_signed,bool>::type unpack_int (
- T& item,
- std::istream& in
- )
- /*!
- requires
- - T is a signed integral type
- ensures
- - if (there are no problems deserializing item) then
- - returns false
- - #item == the value stored in in
- - else
- - returns true
-
- !*/
- {
- COMPILE_TIME_ASSERT(sizeof(T) <= 8);
-
-
- unsigned char buf[8];
- unsigned char size;
- bool is_negative;
-
- std::streambuf* sbuf = in.rdbuf();
-
- item = 0;
- int ch = sbuf->sbumpc();
- if (ch != EOF)
- {
- size = static_cast<unsigned char>(ch);
- }
- else
- {
- in.setstate(std::ios::badbit);
- return true;
- }
-
- if (size&0x80)
- is_negative = true;
- else
- is_negative = false;
- size &= 0x0F;
-
- // check if the serialized object is too big
- if (size > (unsigned long)tmin<sizeof(T),8>::value || size == 0)
- {
- return true;
- }
-
- if (sbuf->sgetn(reinterpret_cast<char*>(&buf),size) != size)
- {
- in.setstate(std::ios::badbit);
- return true;
- }
-
-
- for (unsigned char i = size-1; true; --i)
- {
- item <<= 8;
- item |= buf[i];
- if (i == 0)
- break;
- }
-
- if (is_negative)
- item *= -1;
-
-
- return false;
- }
-
- // ------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- typename disable_if_c<std::numeric_limits<T>::is_signed,bool>::type pack_int (
- T item,
- std::ostream& out
- )
- /*!
- requires
- - T is an unsigned integral type
- ensures
- - if (no problems occur serializing item) then
- - writes item to out
- - returns false
- - else
- - returns true
- !*/
- {
- COMPILE_TIME_ASSERT(sizeof(T) <= 8);
- unsigned char buf[9];
- unsigned char size = sizeof(T);
-
- for (unsigned char i = 1; i <= sizeof(T); ++i)
- {
- buf[i] = static_cast<unsigned char>(item&0xFF);
- item >>= 8;
- if (item == 0) { size = i; break; }
- }
-
- std::streambuf* sbuf = out.rdbuf();
- buf[0] = size;
- if (sbuf->sputn(reinterpret_cast<char*>(buf),size+1) != size+1)
- {
- out.setstate(std::ios::eofbit | std::ios::badbit);
- return true;
- }
-
- return false;
- }
-
- // ------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- typename disable_if_c<std::numeric_limits<T>::is_signed,bool>::type unpack_int (
- T& item,
- std::istream& in
- )
- /*!
- requires
- - T is an unsigned integral type
- ensures
- - if (there are no problems deserializing item) then
- - returns false
- - #item == the value stored in in
- - else
- - returns true
-
- !*/
- {
- COMPILE_TIME_ASSERT(sizeof(T) <= 8);
-
- unsigned char buf[8];
- unsigned char size;
-
- item = 0;
-
- std::streambuf* sbuf = in.rdbuf();
- int ch = sbuf->sbumpc();
- if (ch != EOF)
- {
- size = static_cast<unsigned char>(ch);
- }
- else
- {
- in.setstate(std::ios::badbit);
- return true;
- }
-
-
- // mask out the 3 reserved bits
- size &= 0x8F;
-
- // check if an error occurred
- if (size > (unsigned long)tmin<sizeof(T),8>::value || size == 0)
- return true;
-
-
- if (sbuf->sgetn(reinterpret_cast<char*>(&buf),size) != size)
- {
- in.setstate(std::ios::badbit);
- return true;
- }
-
- for (unsigned char i = size-1; true; --i)
- {
- item <<= 8;
- item |= buf[i];
- if (i == 0)
- break;
- }
-
- return false;
- }
-
- }
-
-// ----------------------------------------------------------------------------------------
-
- #define USE_DEFAULT_INT_SERIALIZATION_FOR(T) \
- inline void serialize (const T& item, std::ostream& out) \
- { if (ser_helper::pack_int(item,out)) throw serialization_error("Error serializing object of type " + std::string(#T)); } \
- inline void deserialize (T& item, std::istream& in) \
- { if (ser_helper::unpack_int(item,in)) throw serialization_error("Error deserializing object of type " + std::string(#T)); }
-
- template <typename T>
- inline bool pack_byte (
- const T& ch,
- std::ostream& out
- )
- {
- std::streambuf* sbuf = out.rdbuf();
- return (sbuf->sputc((char)ch) == EOF);
- }
-
- template <typename T>
- inline bool unpack_byte (
- T& ch,
- std::istream& in
- )
- {
- std::streambuf* sbuf = in.rdbuf();
- int temp = sbuf->sbumpc();
- if (temp != EOF)
- {
- ch = static_cast<T>(temp);
- return false;
- }
- else
- {
- return true;
- }
- }
-
- #define USE_DEFAULT_BYTE_SERIALIZATION_FOR(T) \
- inline void serialize (const T& item,std::ostream& out) \
- { if (pack_byte(item,out)) throw serialization_error("Error serializing object of type " + std::string(#T)); } \
- inline void deserialize (T& item, std::istream& in) \
- { if (unpack_byte(item,in)) throw serialization_error("Error deserializing object of type " + std::string(#T)); }
-
-// ----------------------------------------------------------------------------------------
-
- USE_DEFAULT_INT_SERIALIZATION_FOR(short)
- USE_DEFAULT_INT_SERIALIZATION_FOR(int)
- USE_DEFAULT_INT_SERIALIZATION_FOR(long)
- USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned short)
- USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned int)
- USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned long)
- USE_DEFAULT_INT_SERIALIZATION_FOR(uint64)
- USE_DEFAULT_INT_SERIALIZATION_FOR(int64)
-
- USE_DEFAULT_BYTE_SERIALIZATION_FOR(char)
- USE_DEFAULT_BYTE_SERIALIZATION_FOR(signed char)
- USE_DEFAULT_BYTE_SERIALIZATION_FOR(unsigned char)
-
- // Don't define serialization for wchar_t when using visual studio and
- // _NATIVE_WCHAR_T_DEFINED isn't defined since if it isn't they improperly set
- // wchar_t to be a typedef rather than its own type as required by the C++
- // standard.
-#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED
- USE_DEFAULT_INT_SERIALIZATION_FOR(wchar_t)
-#endif
-
-// ----------------------------------------------------------------------------------------
-
- inline void serialize(
- const float_details& item,
- std::ostream& out
- )
- {
- serialize(item.mantissa, out);
- serialize(item.exponent, out);
- }
-
- inline void deserialize(
- float_details& item,
- std::istream& in
- )
- {
- deserialize(item.mantissa, in);
- deserialize(item.exponent, in);
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T>
- inline void serialize_floating_point (
- const T& item,
- std::ostream& out
- )
- {
- try
- {
- float_details temp = item;
- serialize(temp, out);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing a floating point number."); }
- }
-
- template <typename T>
- inline bool old_deserialize_floating_point (
- T& item,
- std::istream& in
- )
- {
- std::ios::fmtflags oldflags = in.flags();
- in.flags(static_cast<std::ios_base::fmtflags>(0));
- std::streamsize ss = in.precision(35);
- if (in.peek() == 'i')
- {
- item = std::numeric_limits<T>::infinity();
- in.get();
- in.get();
- in.get();
- }
- else if (in.peek() == 'n')
- {
- item = -std::numeric_limits<T>::infinity();
- in.get();
- in.get();
- in.get();
- in.get();
- }
- else if (in.peek() == 'N')
- {
- item = std::numeric_limits<T>::quiet_NaN();
- in.get();
- in.get();
- in.get();
- }
- else
- {
- in >> item;
- }
- in.flags(oldflags);
- in.precision(ss);
- return (in.get() != ' ');
- }
-
- template <typename T>
- inline void deserialize_floating_point (
- T& item,
- std::istream& in
- )
- {
- // check if the serialized data uses the older ASCII based format. We can check
- // this easily because the new format starts with the integer control byte which
- // always has 0 bits in the positions corresponding to the bitmask 0x70. Moreover,
- // since the previous format used ASCII numbers we know that no valid bytes can
- // have bit values of one in the positions indicated 0x70. So this test looks at
- // the first byte and checks if the serialized data uses the old format or the new
- // format.
- if ((in.rdbuf()->sgetc()&0x70) == 0)
- {
- try
- {
- // Use the fast and compact binary serialization format.
- float_details temp;
- deserialize(temp, in);
- item = temp;
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing a floating point number."); }
- }
- else
- {
- if (old_deserialize_floating_point(item, in))
- throw serialization_error("Error deserializing a floating point number.");
- }
- }
-
- inline void serialize ( const float& item, std::ostream& out)
- {
- serialize_floating_point(item,out);
- }
-
- inline void deserialize (float& item, std::istream& in)
- {
- deserialize_floating_point(item,in);
- }
-
- inline void serialize ( const double& item, std::ostream& out)
- {
- serialize_floating_point(item,out);
- }
-
- inline void deserialize (double& item, std::istream& in)
- {
- deserialize_floating_point(item,in);
- }
-
- inline void serialize ( const long double& item, std::ostream& out)
- {
- serialize_floating_point(item,out);
- }
-
- inline void deserialize ( long double& item, std::istream& in)
- {
- deserialize_floating_point(item,in);
- }
-
-// ----------------------------------------------------------------------------------------
-// prototypes
-
- template <typename domain, typename range, typename compare, typename alloc>
- void serialize (
- const std::map<domain,range, compare, alloc>& item,
- std::ostream& out
- );
-
- template <typename domain, typename range, typename compare, typename alloc>
- void deserialize (
- std::map<domain, range, compare, alloc>& item,
- std::istream& in
- );
-
- template <typename domain, typename compare, typename alloc>
- void serialize (
- const std::set<domain, compare, alloc>& item,
- std::ostream& out
- );
-
- template <typename domain, typename compare, typename alloc>
- void deserialize (
- std::set<domain, compare, alloc>& item,
- std::istream& in
- );
-
- template <typename T, typename alloc>
- void serialize (
- const std::vector<T,alloc>& item,
- std::ostream& out
- );
-
- template <typename T, typename alloc>
- void deserialize (
- std::vector<T,alloc>& item,
- std::istream& in
- );
-
- template <typename T, typename alloc>
- void serialize (
- const std::deque<T,alloc>& item,
- std::ostream& out
- );
-
- template <typename T, typename alloc>
- void deserialize (
- std::deque<T,alloc>& item,
- std::istream& in
- );
-
- inline void serialize (
- const std::string& item,
- std::ostream& out
- );
-
- inline void deserialize (
- std::string& item,
- std::istream& in
- );
-
- inline void serialize (
- const std::wstring& item,
- std::ostream& out
- );
-
- inline void deserialize (
- std::wstring& item,
- std::istream& in
- );
-
- inline void serialize (
- const ustring& item,
- std::ostream& out
- );
-
- inline void deserialize (
- ustring& item,
- std::istream& in
- );
-
- template <
- typename T
- >
- inline void serialize (
- const enumerable<T>& item,
- std::ostream& out
- );
-
- template <
- typename domain,
- typename range
- >
- inline void serialize (
- const map_pair<domain,range>& item,
- std::ostream& out
- );
-
- template <
- typename T,
- size_t length
- >
- inline void serialize (
- const T (&array)[length],
- std::ostream& out
- );
-
- template <
- typename T,
- size_t length
- >
- inline void deserialize (
- T (&array)[length],
- std::istream& in
- );
-
-// ----------------------------------------------------------------------------------------
-// ----------------------------------------------------------------------------------------
-// ----------------------------------------------------------------------------------------
-// ----------------------------------------------------------------------------------------
-
- inline void serialize (
- bool item,
- std::ostream& out
- )
- {
- if (item)
- out << '1';
- else
- out << '0';
-
- if (!out)
- throw serialization_error("Error serializing object of type bool");
- }
-
- inline void deserialize (
- bool& item,
- std::istream& in
- )
- {
- int ch = in.get();
- if (ch != EOF)
- {
- if (ch == '1')
- item = true;
- else if (ch == '0')
- item = false;
- else
- throw serialization_error("Error deserializing object of type bool");
- }
- else
- {
- throw serialization_error("Error deserializing object of type bool");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename first_type, typename second_type>
- void serialize (
- const std::pair<first_type, second_type>& item,
- std::ostream& out
- )
- {
- try
- {
- serialize(item.first,out);
- serialize(item.second,out);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::pair"); }
- }
-
- template <typename first_type, typename second_type>
- void deserialize (
- std::pair<first_type, second_type>& item,
- std::istream& in
- )
- {
- try
- {
- deserialize(item.first,in);
- deserialize(item.second,in);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::pair"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename domain, typename range, typename compare, typename alloc>
- void serialize (
- const std::map<domain,range, compare, alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
-
- serialize(size,out);
- typename std::map<domain,range,compare,alloc>::const_iterator i;
- for (i = item.begin(); i != item.end(); ++i)
- {
- serialize(i->first,out);
- serialize(i->second,out);
- }
-
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::map"); }
- }
-
- template <typename domain, typename range, typename compare, typename alloc>
- void deserialize (
- std::map<domain, range, compare, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- item.clear();
-
- unsigned long size;
- deserialize(size,in);
- domain d;
- range r;
- for (unsigned long i = 0; i < size; ++i)
- {
- deserialize(d,in);
- deserialize(r,in);
- item[d] = r;
- }
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::map"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename domain, typename compare, typename alloc>
- void serialize (
- const std::set<domain, compare, alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
-
- serialize(size,out);
- typename std::set<domain,compare,alloc>::const_iterator i;
- for (i = item.begin(); i != item.end(); ++i)
- {
- serialize(*i,out);
- }
-
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::set"); }
- }
-
- template <typename domain, typename compare, typename alloc>
- void deserialize (
- std::set<domain, compare, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- item.clear();
-
- unsigned long size;
- deserialize(size,in);
- domain d;
- for (unsigned long i = 0; i < size; ++i)
- {
- deserialize(d,in);
- item.insert(d);
- }
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::set"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename alloc>
- void serialize (
- const std::vector<bool,alloc>& item,
- std::ostream& out
- )
- {
- std::vector<unsigned char> temp(item.size());
- for (unsigned long i = 0; i < item.size(); ++i)
- {
- if (item[i])
- temp[i] = '1';
- else
- temp[i] = '0';
- }
- serialize(temp, out);
- }
-
- template <typename alloc>
- void deserialize (
- std::vector<bool,alloc>& item,
- std::istream& in
- )
- {
- std::vector<unsigned char> temp;
- deserialize(temp, in);
- item.resize(temp.size());
- for (unsigned long i = 0; i < temp.size(); ++i)
- {
- if (temp[i] == '1')
- item[i] = true;
- else
- item[i] = false;
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T, typename alloc>
- void serialize (
- const std::vector<T,alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
-
- serialize(size,out);
- for (unsigned long i = 0; i < item.size(); ++i)
- serialize(item[i],out);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::vector"); }
- }
-
- template <typename T, typename alloc>
- void deserialize (
- std::vector<T, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- unsigned long size;
- deserialize(size,in);
- item.resize(size);
- for (unsigned long i = 0; i < size; ++i)
- deserialize(item[i],in);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename alloc>
- void serialize (
- const std::vector<char,alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
- serialize(size,out);
- if (item.size() != 0)
- out.write(&item[0], item.size());
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::vector"); }
- }
-
- template <typename alloc>
- void deserialize (
- std::vector<char, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- unsigned long size;
- deserialize(size,in);
- item.resize(size);
- if (item.size() != 0)
- in.read(&item[0], item.size());
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename alloc>
- void serialize (
- const std::vector<unsigned char,alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
- serialize(size,out);
- if (item.size() != 0)
- out.write((char*)&item[0], item.size());
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::vector"); }
- }
-
- template <typename alloc>
- void deserialize (
- std::vector<unsigned char, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- unsigned long size;
- deserialize(size,in);
- item.resize(size);
- if (item.size() != 0)
- in.read((char*)&item[0], item.size());
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T, typename alloc>
- void serialize (
- const std::deque<T,alloc>& item,
- std::ostream& out
- )
- {
- try
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
-
- serialize(size,out);
- for (unsigned long i = 0; i < item.size(); ++i)
- serialize(item[i],out);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::deque"); }
- }
-
- template <typename T, typename alloc>
- void deserialize (
- std::deque<T, alloc>& item,
- std::istream& in
- )
- {
- try
- {
- unsigned long size;
- deserialize(size,in);
- item.resize(size);
- for (unsigned long i = 0; i < size; ++i)
- deserialize(item[i],in);
- }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::deque"); }
- }
-
-// ----------------------------------------------------------------------------------------
-
- inline void serialize (
- const std::string& item,
- std::ostream& out
- )
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
- try{ serialize(size,out); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::string"); }
-
- out.write(item.c_str(),size);
- if (!out) throw serialization_error("Error serializing object of type std::string");
- }
-
- inline void deserialize (
- std::string& item,
- std::istream& in
- )
- {
- unsigned long size;
- try { deserialize(size,in); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::string"); }
-
- item.resize(size);
- if (size != 0)
- {
- in.read(&item[0],size);
- if (!in) throw serialization_error("Error deserializing object of type std::string");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- inline void serialize (
- const std::wstring& item,
- std::ostream& out
- )
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
- try{ serialize(size,out); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type std::wstring"); }
-
- for (unsigned long i = 0; i < item.size(); ++i)
- serialize(item[i], out);
- if (!out) throw serialization_error("Error serializing object of type std::wstring");
- }
-
- inline void deserialize (
- std::wstring& item,
- std::istream& in
- )
- {
- unsigned long size;
- try { deserialize(size,in); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type std::wstring"); }
-
- item.resize(size);
- for (unsigned long i = 0; i < item.size(); ++i)
- deserialize(item[i],in);
-
- if (!in) throw serialization_error("Error deserializing object of type std::wstring");
- }
-
-// ----------------------------------------------------------------------------------------
-
- inline void serialize (
- const ustring& item,
- std::ostream& out
- )
- {
- const unsigned long size = static_cast<unsigned long>(item.size());
- try{ serialize(size,out); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while serializing object of type ustring"); }
-
- for (unsigned long i = 0; i < item.size(); ++i)
- serialize(item[i], out);
- if (!out) throw serialization_error("Error serializing object of type ustring");
- }
-
- inline void deserialize (
- ustring& item,
- std::istream& in
- )
- {
- unsigned long size;
- try { deserialize(size,in); }
- catch (serialization_error& e)
- { throw serialization_error(e.info + "\n while deserializing object of type ustring"); }
-
- item.resize(size);
- for (unsigned long i = 0; i < item.size(); ++i)
- deserialize(item[i],in);
-
- if (!in) throw serialization_error("Error deserializing object of type ustring");
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- inline void serialize (
- const enumerable<T>& item,
- std::ostream& out
- )
- {
- try
- {
- item.reset();
- serialize(item.size(),out);
- while (item.move_next())
- serialize(item.element(),out);
- item.reset();
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while serializing object of type enumerable");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename domain,
- typename range
- >
- inline void serialize (
- const map_pair<domain,range>& item,
- std::ostream& out
- )
- {
- try
- {
- serialize(item.key(),out);
- serialize(item.value(),out);
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while serializing object of type map_pair");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename T,
- size_t length
- >
- inline void serialize (
- const T (&array)[length],
- std::ostream& out
- )
- {
- try
- {
- serialize(length,out);
- for (size_t i = 0; i < length; ++i)
- serialize(array[i],out);
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while serializing a C style array");
- }
- }
-
- 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 <
- typename T,
- size_t length
- >
- inline void deserialize (
- T (&array)[length],
- std::istream& in
- )
- {
- size_t size;
- try
- {
- deserialize(size,in);
- if (size == length)
- {
- for (size_t i = 0; i < length; ++i)
- deserialize(array[i],in);
- }
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while deserializing a C style array");
- }
-
- if (size != length)
- 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 <
- typename T,
- size_t N
- >
- inline void serialize (
- const std::array<T,N>& array,
- std::ostream& out
- )
- {
- typedef T c_array_type[N];
- serialize(*(const c_array_type*)array.data(), out);
- }
-
- template <
- typename T,
- size_t N
- >
- inline void deserialize (
- std::array<T,N>& array,
- std::istream& in
- )
- {
- typedef T c_array_type[N];
- deserialize(*(c_array_type*)array.data(), in);
- }
-
- template <
- typename T
- >
- inline void serialize (
- const std::array<T,0>& /*array*/,
- std::ostream& out
- )
- {
- size_t N = 0;
- serialize(N, out);
- }
-
- template <
- typename T
- >
- inline void deserialize (
- std::array<T,0>& /*array*/,
- std::istream& in
- )
- {
- size_t N;
- deserialize(N, in);
- if (N != 0)
- {
- std::ostringstream sout;
- sout << "Expected std::array of size 0 but found a size of " << N;
- throw serialization_error(sout.str());
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- inline void serialize (
- const std::complex<T>& item,
- std::ostream& out
- )
- {
- try
- {
- serialize(item.real(),out);
- serialize(item.imag(),out);
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while serializing an object of type std::complex");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- template <
- typename T
- >
- inline void deserialize (
- std::complex<T>& item,
- std::istream& in
- )
- {
- try
- {
- T real, imag;
- deserialize(real,in);
- deserialize(imag,in);
- item = std::complex<T>(real,imag);
- }
- catch (serialization_error& e)
- {
- throw serialization_error(e.info + "\n while deserializing an object of type std::complex");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- class proxy_serialize
- {
- public:
- explicit proxy_serialize (
- const std::string& filename
- )
- {
- fout.reset(new std::ofstream(filename.c_str(), std::ios::binary));
- if (!(*fout))
- throw serialization_error("Unable to open " + filename + " for writing.");
- }
-
- template <typename T>
- inline proxy_serialize& operator<<(const T& item)
- {
- serialize(item, *fout);
- return *this;
- }
-
- private:
- std::shared_ptr<std::ofstream> fout;
- };
-
- class proxy_deserialize
- {
- public:
- explicit proxy_deserialize (
- const std::string& filename
- ) : filename(filename)
- {
- fin.reset(new std::ifstream(filename.c_str(), std::ios::binary));
- 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);
- }
-
- template <typename T>
- inline proxy_deserialize& operator>>(T& item)
- {
- return doit(item);
- }
-
- template <typename T>
- inline proxy_deserialize& operator>>(ramdump_t<T>&& item)
- {
- return doit(std::move(item));
- }
-
- 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);
- }
- catch (serialization_error& e)
- {
- std::string suffix;
- if (looks_like_a_compressed_file())
- suffix = "\n *** THIS LOOKS LIKE A COMPRESSED FILE. DID YOU FORGET TO DECOMPRESS IT? *** \n";
-
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- }
- ++objects_read;
- return *this;
- }
-
- int objects_read = 0;
- std::string filename;
- std::shared_ptr<std::ifstream> 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.
- // Then it turns out that the problem is they have a compressed file that NEEDS TO
- // BE DECOMPRESSED by bzip2 or whatever and the reason they are getting
- // deserialization errors is because they didn't decompress the file. So we are
- // going to check if this file looks like a compressed file and if so then emit an
- // error message telling them to unzip the file. :(
- char file_header[4] = {0,0,0,0};
-
- bool looks_like_a_compressed_file(
- ) const
- {
- if (file_header[0] == 'B' && file_header[1] == 'Z' && file_header[2] == 'h' &&
- ('0' <= file_header[3] && file_header[3] <= '9') )
- {
- return true;
- }
-
- return false;
- }
- };
-
- inline proxy_serialize serialize(const std::string& filename)
- { return proxy_serialize(filename); }
- inline proxy_deserialize deserialize(const std::string& filename)
- { return proxy_deserialize(filename); }
-
-// ----------------------------------------------------------------------------------------
-
-}
-
-// forward declare the MessageLite object so we can reference it below.
-namespace google
-{
- namespace protobuf
- {
- class MessageLite;
- }
-}
-
-namespace dlib
-{
-
- /*!A is_protocol_buffer
- This is a template that tells you if a type is a Google protocol buffer object.
- !*/
-
- template <typename T, typename U = void >
- struct is_protocol_buffer
- {
- static const bool value = false;
- };
-
- template <typename T>
- struct is_protocol_buffer <T,typename enable_if<is_convertible<T*,::google::protobuf::MessageLite*> >::type >
- {
- static const bool value = true;
- };
-
- template <typename T>
- typename enable_if<is_protocol_buffer<T> >::type serialize(const T& item, std::ostream& out)
- {
- // Note that Google protocol buffer messages are not self delimiting
- // (see https://developers.google.com/protocol-buffers/docs/techniques)
- // This means they don't record their length or where they end, so we have
- // to record this information ourselves. So we save the size as a little endian 32bit
- // integer prefixed onto the front of the message.
-
- byte_orderer bo;
-
- // serialize into temp string
- std::string temp;
- if (!item.SerializeToString(&temp))
- throw dlib::serialization_error("Error while serializing a Google Protocol Buffer object.");
- if (temp.size() > std::numeric_limits<uint32>::max())
- throw dlib::serialization_error("Error while serializing a Google Protocol Buffer object, message too large.");
-
- // write temp to the output stream
- uint32 size = temp.size();
- bo.host_to_little(size);
- out.write((char*)&size, sizeof(size));
- out.write(temp.c_str(), temp.size());
- }
-
- template <typename T>
- typename enable_if<is_protocol_buffer<T> >::type deserialize(T& item, std::istream& in)
- {
- // Note that Google protocol buffer messages are not self delimiting
- // (see https://developers.google.com/protocol-buffers/docs/techniques)
- // This means they don't record their length or where they end, so we have
- // to record this information ourselves. So we save the size as a little endian 32bit
- // integer prefixed onto the front of the message.
-
- byte_orderer bo;
-
- uint32 size = 0;
- // read the size
- in.read((char*)&size, sizeof(size));
- bo.little_to_host(size);
- if (!in || size == 0)
- throw dlib::serialization_error("Error while deserializing a Google Protocol Buffer object.");
-
- // read the bytes into temp
- std::string temp;
- temp.resize(size);
- in.read(&temp[0], size);
-
- // parse temp into item
- if (!in || !item.ParseFromString(temp))
- {
- throw dlib::serialization_error("Error while deserializing a Google Protocol Buffer object.");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
- inline void check_serialized_version(const std::string& expected_version, std::istream& in)
- {
- std::string version;
- deserialize(version, in);
- if (version != expected_version)
- {
- throw serialization_error("Unexpected version '"+version+
- "' found while deserializing object. Expected version to be '"+expected_version+"'.");
- }
- }
-
-// ----------------------------------------------------------------------------------------
-
-}
-
-#endif // DLIB_SERIALIZe_
-