/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 | |
// basic_binary_oprimitive.ipp: | |
// (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 <ostream> | |
#include <cstddef> // NULL | |
#include <cstring> | |
#include <boost/config.hpp> | |
#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) | |
namespace std{ | |
using ::strlen; | |
} // namespace std | |
#endif | |
#ifndef BOOST_NO_CWCHAR | |
#include <cwchar> | |
#ifdef BOOST_NO_STDC_NAMESPACE | |
namespace std{ using ::wcslen; } | |
#endif | |
#endif | |
#include <boost/detail/workaround.hpp> | |
#include <boost/archive/add_facet.hpp> | |
#include <boost/archive/codecvt_null.hpp> | |
namespace boost { | |
namespace archive { | |
////////////////////////////////////////////////////////////////////// | |
// implementation of basic_binary_oprimitive | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) | |
basic_binary_oprimitive<Archive, Elem, Tr>::init() | |
{ | |
// record native sizes of fundamental types | |
// this is to permit detection of attempts to pass | |
// native binary archives accross incompatible machines. | |
// This is not foolproof but its better than nothing. | |
this->This()->save(static_cast<unsigned char>(sizeof(int))); | |
this->This()->save(static_cast<unsigned char>(sizeof(long))); | |
this->This()->save(static_cast<unsigned char>(sizeof(float))); | |
this->This()->save(static_cast<unsigned char>(sizeof(double))); | |
// for checking endianness | |
this->This()->save(int(1)); | |
} | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) | |
basic_binary_oprimitive<Archive, Elem, Tr>::save(const char * s) | |
{ | |
std::size_t l = std::strlen(s); | |
this->This()->save(l); | |
save_binary(s, l); | |
} | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) | |
basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::string &s) | |
{ | |
std::size_t l = static_cast<std::size_t>(s.size()); | |
this->This()->save(l); | |
save_binary(s.data(), l); | |
} | |
#ifndef BOOST_NO_CWCHAR | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) | |
basic_binary_oprimitive<Archive, Elem, Tr>::save(const wchar_t * ws) | |
{ | |
std::size_t l = std::wcslen(ws); | |
this->This()->save(l); | |
save_binary(ws, l * sizeof(wchar_t) / sizeof(char)); | |
} | |
#endif | |
#ifndef BOOST_NO_STD_WSTRING | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) | |
basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::wstring &ws) | |
{ | |
std::size_t l = ws.size(); | |
this->This()->save(l); | |
save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); | |
} | |
#endif | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) | |
basic_binary_oprimitive<Archive, Elem, Tr>::basic_binary_oprimitive( | |
std::basic_streambuf<Elem, Tr> & sb, | |
bool no_codecvt | |
) : | |
#ifndef BOOST_NO_STD_LOCALE | |
m_sb(sb), | |
archive_locale(NULL), | |
locale_saver(m_sb) | |
{ | |
if(! no_codecvt){ | |
archive_locale.reset( | |
add_facet( | |
std::locale::classic(), | |
new codecvt_null<Elem> | |
) | |
); | |
m_sb.pubimbue(* archive_locale); | |
} | |
} | |
#else | |
m_sb(sb) | |
{} | |
#endif | |
// some libraries including stl and libcomo fail if the | |
// buffer isn't flushed before the code_cvt facet is changed. | |
// I think this is a bug. We explicity invoke sync to when | |
// we're done with the streambuf to work around this problem. | |
// Note that sync is a protected member of stream buff so we | |
// have to invoke it through a contrived derived class. | |
namespace detail { | |
// note: use "using" to get past msvc bug | |
using namespace std; | |
template<class Elem, class Tr> | |
class output_streambuf_access : public std::basic_streambuf<Elem, Tr> { | |
public: | |
virtual int sync(){ | |
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) | |
return this->basic_streambuf::sync(); | |
#else | |
return this->basic_streambuf<Elem, Tr>::sync(); | |
#endif | |
} | |
}; | |
} // detail | |
// scoped_ptr requires that g be a complete type at time of | |
// destruction so define destructor here rather than in the header | |
template<class Archive, class Elem, class Tr> | |
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) | |
basic_binary_oprimitive<Archive, Elem, Tr>::~basic_binary_oprimitive(){ | |
// flush buffer | |
//destructor can't throw | |
try{ | |
static_cast<detail::output_streambuf_access<Elem, Tr> &>(m_sb).sync(); | |
} | |
catch(...){ | |
} | |
} | |
} // namespace archive | |
} // namespace boost |