| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 | #ifndef BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP#define BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP// MS compatible compilers support #pragma once#if defined(_MSC_VER)# pragma once#endif/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8// basic_text_oprimitive.hpp// (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.// archives stored as text - note these ar templated on the basic// stream templates to accommodate wide (and other?) kind of characters//// note the fact that on libraries without wide characters, ostream is// is not a specialization of basic_ostream which in fact is not defined// in such cases.   So we can't use basic_ostream<OStream::char_type> but rather// use two template parameters#include <iomanip>#include <locale>#include <cstddef> // size_t#include <boost/config.hpp>#include <boost/static_assert.hpp>#include <boost/io/ios_state.hpp>#include <boost/detail/workaround.hpp>#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)#include <boost/archive/dinkumware.hpp>#endif#if defined(BOOST_NO_STDC_NAMESPACE)namespace std{    using ::size_t;    #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT)        using ::locale;    #endif} // namespace std#endif#include <boost/type_traits/is_floating_point.hpp>#include <boost/mpl/bool.hpp>#include <boost/limits.hpp>#include <boost/integer.hpp>#include <boost/io/ios_state.hpp>#include <boost/serialization/throw_exception.hpp>#include <boost/archive/basic_streambuf_locale_saver.hpp>#include <boost/archive/codecvt_null.hpp>#include <boost/archive/archive_exception.hpp>#include <boost/archive/detail/abi_prefix.hpp> // must be the last headernamespace boost {namespace archive {/////////////////////////////////////////////////////////////////////////// class basic_text_oprimitive - output of prmitives to streamtemplate<class OStream>class BOOST_SYMBOL_VISIBLE basic_text_oprimitive{protected:    OStream &os;    io::ios_flags_saver flags_saver;    io::ios_precision_saver precision_saver;    #ifndef BOOST_NO_STD_LOCALE    // note order! - if you change this, libstd++ will fail!    // a) create new locale with new codecvt facet    // b) save current locale    // c) change locale to new one    // d) use stream buffer    // e) change locale back to original    // f) destroy new codecvt facet    boost::archive::codecvt_null<typename OStream::char_type> codecvt_null_facet;    std::locale archive_locale;    basic_ostream_locale_saver<        typename OStream::char_type,        typename OStream::traits_type    > locale_saver;    #endif    /////////////////////////////////////////////////////////    // fundamental types that need special treatment    void save(const bool t){        // trap usage of invalid uninitialized boolean which would        // otherwise crash on load.        BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t));        if(os.fail())            boost::serialization::throw_exception(                archive_exception(archive_exception::output_stream_error)            );        os << t;    }    void save(const signed char t)    {        save(static_cast<short int>(t));    }    void save(const unsigned char t)    {        save(static_cast<short unsigned int>(t));    }    void save(const char t)    {        save(static_cast<short int>(t));    }    #ifndef BOOST_NO_INTRINSIC_WCHAR_T    void save(const wchar_t t)    {        BOOST_STATIC_ASSERT(sizeof(wchar_t) <= sizeof(int));        save(static_cast<int>(t));    }    #endif    /////////////////////////////////////////////////////////    // saving of any types not listed above    template<class T>    void save_impl(const T &t, boost::mpl::bool_<false> &){        if(os.fail())            boost::serialization::throw_exception(                archive_exception(archive_exception::output_stream_error)            );        os << t;    }    /////////////////////////////////////////////////////////    // floating point types need even more special treatment    // the following determines whether the type T is some sort    // of floating point type.  Note that we then assume that    // the stream << operator is defined on that type - if not    // we'll get a compile time error. This is meant to automatically    // support synthesized types which support floating point    // operations. Also it should handle compiler dependent types    // such long double.  Due to John Maddock.    template<class T>    struct is_float {        typedef typename mpl::bool_<            boost::is_floating_point<T>::value            || (std::numeric_limits<T>::is_specialized            && !std::numeric_limits<T>::is_integer            && !std::numeric_limits<T>::is_exact            && std::numeric_limits<T>::max_exponent)        >::type type;    };    template<class T>    void save_impl(const T &t, boost::mpl::bool_<true> &){        // must be a user mistake - can't serialize un-initialized data        if(os.fail()){            boost::serialization::throw_exception(                archive_exception(archive_exception::output_stream_error)            );        }        // The formulae for the number of decimla digits required is given in        // http://www2.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1822.pdf        // which is derived from Kahan's paper:        // www.eecs.berkeley.edu/~wkahan/ieee754status/ieee754.ps        // const unsigned int digits = (std::numeric_limits<T>::digits * 3010) / 10000;        // note: I've commented out the above because I didn't get good results.  e.g.        // in one case I got a difference of 19 units.        #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS            const unsigned int digits = std::numeric_limits<T>::max_digits10;        #else            const unsigned int digits = std::numeric_limits<T>::digits10 + 2;        #endif        os << std::setprecision(digits) << std::scientific << t;    }    template<class T>    void save(const T & t){        typename is_float<T>::type tf;        save_impl(t, tf);    }    BOOST_ARCHIVE_OR_WARCHIVE_DECL    basic_text_oprimitive(OStream & os, bool no_codecvt);    BOOST_ARCHIVE_OR_WARCHIVE_DECL    ~basic_text_oprimitive();public:    // unformatted append of one character    void put(typename OStream::char_type c){        if(os.fail())            boost::serialization::throw_exception(                archive_exception(archive_exception::output_stream_error)            );        os.put(c);    }    // unformatted append of null terminated string    void put(const char * s){        while('\0' != *s)            os.put(*s++);    }    BOOST_ARCHIVE_OR_WARCHIVE_DECL void    save_binary(const void *address, std::size_t count);};} //namespace boost} //namespace archive#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas#endif // BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP
 |