monero/external/boost/archive/portable_binary_iarchive.hpp
moneromooo-monero c1fa4a7f8c
boost: fix little/big endian compatibility
When no little/big endian flag is given to the writer, it stores
data in host endianness. When loading, if no flag is set, it also
assumes host endianness. This works as long as the loading and
writing are done on machines with the same endianness.

We change this to default to little endian when saving. This will
cause the loader to see the little endian flag, and swap endianness
when loading on a big endian machine. Similarly, writing on a big
endian machine will swap on save, and a little endian machine will
load little endian data.
2019-09-04 14:54:00 +00:00

376 lines
12 KiB
C++

#ifndef PORTABLE_BINARY_IARCHIVE_HPP
#define PORTABLE_BINARY_IARCHIVE_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4244 )
#endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// portable_binary_iarchive.hpp
// (C) Copyright 2002-7 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <istream>
#include <boost/version.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/item_version_type.hpp>
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_binary_iprimitive.hpp>
#include <boost/archive/detail/common_iarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/archive/portable_binary_archive.hpp>
#include <boost/archive/impl/basic_binary_iprimitive.ipp>
namespace boost { namespace archive {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// exception to be thrown if integer read from archive doesn't fit
// variable being loaded
class portable_binary_iarchive_exception :
public boost::archive::archive_exception
{
public:
enum exception_code {
incompatible_integer_size
} m_exception_code ;
portable_binary_iarchive_exception(exception_code c = incompatible_integer_size ) :
boost::archive::archive_exception(boost::archive::archive_exception::other_exception),
m_exception_code(c)
{}
virtual const char *what( ) const throw( )
{
const char *msg = "programmer error";
switch(m_exception_code){
case incompatible_integer_size:
msg = "integer cannot be represented";
break;
default:
msg = boost::archive::archive_exception::what();
assert(false);
break;
}
return msg;
}
};
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// "Portable" input binary archive. It addresses integer size and endienness so
// that binary archives can be passed across systems. Note:floating point types
// not addressed here
class portable_binary_iarchive :
public boost::archive::basic_binary_iprimitive<
portable_binary_iarchive,
std::istream::char_type,
std::istream::traits_type
>,
public boost::archive::detail::common_iarchive<
portable_binary_iarchive
>
{
typedef boost::archive::basic_binary_iprimitive<
portable_binary_iarchive,
std::istream::char_type,
std::istream::traits_type
> primitive_base_t;
typedef boost::archive::detail::common_iarchive<
portable_binary_iarchive
> archive_base_t;
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
#else
friend archive_base_t;
friend primitive_base_t; // since with override load below
friend class boost::archive::detail::interface_iarchive<
portable_binary_iarchive
>;
friend class boost::archive::load_access;
protected:
#endif
unsigned int m_flags;
void load_impl(boost::intmax_t & l, char maxsize);
// default fall through for any types not specified here
template<class T>
void load(T & t){
boost::intmax_t l;
load_impl(l, sizeof(T));
// use cast to avoid compile time warning
//t = static_cast< T >(l);
t = T(l);
}
void load(boost::serialization::item_version_type & t){
boost::intmax_t l;
load_impl(l, sizeof(boost::serialization::item_version_type));
// use cast to avoid compile time warning
t = boost::serialization::item_version_type(l);
}
void load(boost::archive::version_type & t){
boost::intmax_t l;
load_impl(l, sizeof(boost::archive::version_type));
// use cast to avoid compile time warning
t = boost::archive::version_type(l);
}
void load(boost::archive::class_id_type & t){
boost::intmax_t l;
load_impl(l, sizeof(boost::archive::class_id_type));
// use cast to avoid compile time warning
t = boost::archive::class_id_type(static_cast<int>(l));
}
void load(std::string & t){
this->primitive_base_t::load(t);
}
#ifndef BOOST_NO_STD_WSTRING
void load(std::wstring & t){
this->primitive_base_t::load(t);
}
#endif
void load(float & t){
this->primitive_base_t::load(t);
// floats not supported
//BOOST_STATIC_ASSERT(false);
}
void load(double & t){
this->primitive_base_t::load(t);
// doubles not supported
//BOOST_STATIC_ASSERT(false);
}
void load(char & t){
this->primitive_base_t::load(t);
}
void load(unsigned char & t){
this->primitive_base_t::load(t);
}
typedef boost::archive::detail::common_iarchive<portable_binary_iarchive>
detail_common_iarchive;
#if BOOST_VERSION > 105800
template<class T>
void load_override(T & t){
this->detail_common_iarchive::load_override(t);
}
void load_override(boost::archive::class_name_type & t);
// binary files don't include the optional information
void load_override(boost::archive::class_id_optional_type &){}
#else
template<class T>
void load_override(T & t, int){
this->detail_common_iarchive::load_override(t, 0);
}
void load_override(boost::archive::class_name_type & t, int);
// binary files don't include the optional information
void load_override(boost::archive::class_id_optional_type &, int){}
#endif
void init(unsigned int flags);
public:
portable_binary_iarchive(std::istream & is, unsigned flags = 0) :
primitive_base_t(
* is.rdbuf(),
0 != (flags & boost::archive::no_codecvt)
),
archive_base_t(flags),
m_flags(0)
{
init(flags);
}
portable_binary_iarchive(
std::basic_streambuf<
std::istream::char_type,
std::istream::traits_type
> & bsb,
unsigned int flags
) :
primitive_base_t(
bsb,
0 != (flags & boost::archive::no_codecvt)
),
archive_base_t(flags),
m_flags(0)
{
init(flags);
}
};
} }
// required by export in boost version > 1.34
#ifdef BOOST_SERIALIZATION_REGISTER_ARCHIVE
BOOST_SERIALIZATION_REGISTER_ARCHIVE(portable_binary_iarchive)
#endif
// required by export in boost <= 1.34
#define BOOST_ARCHIVE_CUSTOM_IARCHIVE_TYPES portable_binary_iarchive
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// portable_binary_iarchive.cpp
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <istream>
#include <string>
#include <boost/predef/other/endian.h>
#include <boost/serialization/throw_exception.hpp>
#include <boost/archive/archive_exception.hpp>
namespace boost { namespace archive {
inline void
portable_binary_iarchive::load_impl(boost::intmax_t & l, char maxsize){
signed char size;
l = 0;
this->primitive_base_t::load(size);
if(0 == size){
return;
}
bool negative = (size < 0);
if(negative)
size = -size;
if(size > maxsize)
boost::serialization::throw_exception(
portable_binary_iarchive_exception()
);
char * cptr = reinterpret_cast<char *>(& l);
#if BOOST_ENDIAN_BIG_BYTE
cptr += (sizeof(boost::intmax_t) - size);
#endif
this->primitive_base_t::load_binary(cptr, size);
#if BOOST_ENDIAN_BIG_BYTE
if((m_flags & endian_little) || (!(m_flags & endian_big)))
#else
if(m_flags & endian_big)
#endif
reverse_bytes(size, cptr);
if(negative)
l = -l;
}
#if BOOST_VERSION > 105800
inline void
portable_binary_iarchive::load_override(
boost::archive::class_name_type & t
){
std::string cn;
cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE);
load_override(cn);
if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1))
boost::serialization::throw_exception(
boost::archive::archive_exception(
boost::archive::archive_exception::invalid_class_name)
);
std::memcpy(t, cn.data(), cn.size());
// borland tweak
t.t[cn.size()] = '\0';
}
#else
inline void
portable_binary_iarchive::load_override(
boost::archive::class_name_type & t, int
){
std::string cn;
cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE);
load_override(cn, 0);
if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1))
boost::serialization::throw_exception(
boost::archive::archive_exception(
boost::archive::archive_exception::invalid_class_name)
);
std::memcpy(t, cn.data(), cn.size());
// borland tweak
t.t[cn.size()] = '\0';
}
#endif
inline void
portable_binary_iarchive::init(unsigned int flags){
if(0 == (flags & boost::archive::no_header)){
// read signature in an archive version independent manner
std::string file_signature;
* this >> file_signature;
if(file_signature != boost::archive::BOOST_ARCHIVE_SIGNATURE())
boost::serialization::throw_exception(
boost::archive::archive_exception(
boost::archive::archive_exception::invalid_signature
)
);
// make sure the version of the reading archive library can
// support the format of the archive being read
boost::archive::library_version_type input_library_version;
* this >> input_library_version;
// ignore archive version checking
/*
// extra little .t is to get around borland quirk
if(boost::archive::BOOST_ARCHIVE_VERSION() < input_library_version)
boost::serialization::throw_exception(
boost::archive::archive_exception(
boost::archive::archive_exception::unsupported_version
)
);
*/
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
this->set_library_version(input_library_version);
//#else
//#if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
//detail::
//#endif
boost::archive::detail::basic_iarchive::set_library_version(
input_library_version
);
#endif
}
if (!(m_flags & (endian_little | endian_big)))
m_flags |= endian_little;
unsigned char x;
load(x);
m_flags = x << CHAR_BIT;
}
} }
namespace boost {
namespace archive {
namespace detail {
template class archive_serializer_map<portable_binary_iarchive>;
}
// template class basic_binary_iprimitive<
// portable_binary_iarchive,
// std::istream::char_type,
// std::istream::traits_type
//> ;
} // namespace archive
} // namespace boost
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
#endif // PORTABLE_BINARY_IARCHIVE_HPP