diff options
Diffstat (limited to 'ml/dlib/dlib/serialize.h')
-rw-r--r-- | ml/dlib/dlib/serialize.h | 1779 |
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_ - |