]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #ifndef BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP |
2 | #define BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP | |
3 | ||
4 | // MS compatible compilers support #pragma once | |
5 | #if defined(_MSC_VER) | |
6 | # pragma once | |
7 | #endif | |
8 | ||
9 | #if defined(_MSC_VER) | |
10 | #pragma warning( disable : 4800 ) | |
11 | #endif | |
12 | ||
13 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 | |
14 | // basic_binary_iprimitive.hpp | |
15 | // | |
16 | // archives stored as native binary - this should be the fastest way | |
17 | // to archive the state of a group of obects. It makes no attempt to | |
18 | // convert to any canonical form. | |
19 | ||
20 | // IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE | |
21 | // ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON | |
22 | ||
23 | // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . | |
24 | // Use, modification and distribution is subject to the Boost Software | |
25 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
26 | // http://www.boost.org/LICENSE_1_0.txt) | |
27 | ||
28 | // See http://www.boost.org for updates, documentation, and revision history. | |
29 | ||
30 | #include <iosfwd> | |
31 | #include <boost/assert.hpp> | |
32 | #include <locale> | |
33 | #include <cstring> // std::memcpy | |
34 | #include <cstddef> // std::size_t | |
35 | #include <streambuf> // basic_streambuf | |
36 | #include <string> | |
37 | ||
38 | #include <boost/config.hpp> | |
39 | #if defined(BOOST_NO_STDC_NAMESPACE) | |
40 | namespace std{ | |
41 | using ::memcpy; | |
42 | using ::size_t; | |
43 | } // namespace std | |
44 | #endif | |
45 | ||
46 | #include <boost/cstdint.hpp> | |
47 | #include <boost/serialization/throw_exception.hpp> | |
48 | #include <boost/integer.hpp> | |
49 | #include <boost/integer_traits.hpp> | |
50 | ||
51 | //#include <boost/mpl/placeholders.hpp> | |
52 | #include <boost/serialization/is_bitwise_serializable.hpp> | |
53 | #include <boost/serialization/array.hpp> | |
54 | ||
55 | #include <boost/archive/basic_streambuf_locale_saver.hpp> | |
56 | #include <boost/archive/codecvt_null.hpp> | |
57 | #include <boost/archive/archive_exception.hpp> | |
58 | #include <boost/archive/detail/auto_link_archive.hpp> | |
59 | #include <boost/archive/detail/abi_prefix.hpp> // must be the last header | |
60 | ||
61 | namespace boost { | |
62 | namespace archive { | |
63 | ||
64 | ///////////////////////////////////////////////////////////////////////////// | |
65 | // class binary_iarchive - read serialized objects from a input binary stream | |
66 | template<class Archive, class Elem, class Tr> | |
67 | class BOOST_SYMBOL_VISIBLE basic_binary_iprimitive { | |
68 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | |
69 | friend class load_access; | |
70 | protected: | |
71 | #else | |
72 | public: | |
73 | #endif | |
74 | std::basic_streambuf<Elem, Tr> & m_sb; | |
75 | // return a pointer to the most derived class | |
76 | Archive * This(){ | |
77 | return static_cast<Archive *>(this); | |
78 | } | |
79 | ||
80 | #ifndef BOOST_NO_STD_LOCALE | |
81 | // note order! - if you change this, libstd++ will fail! | |
82 | // a) create new locale with new codecvt facet | |
83 | // b) save current locale | |
84 | // c) change locale to new one | |
85 | // d) use stream buffer | |
86 | // e) change locale back to original | |
87 | // f) destroy new codecvt facet | |
88 | boost::archive::codecvt_null<Elem> codecvt_null_facet; | |
89 | basic_streambuf_locale_saver<Elem, Tr> locale_saver; | |
90 | std::locale archive_locale; | |
91 | #endif | |
92 | ||
93 | // main template for serilization of primitive types | |
94 | template<class T> | |
95 | void load(T & t){ | |
96 | load_binary(& t, sizeof(T)); | |
97 | } | |
98 | ||
99 | ///////////////////////////////////////////////////////// | |
100 | // fundamental types that need special treatment | |
101 | ||
102 | // trap usage of invalid uninitialized boolean | |
103 | void load(bool & t){ | |
104 | load_binary(& t, sizeof(t)); | |
105 | int i = t; | |
106 | BOOST_ASSERT(0 == i || 1 == i); | |
107 | (void)i; // warning suppression for release builds. | |
108 | } | |
109 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void | |
110 | load(std::string &s); | |
111 | #ifndef BOOST_NO_STD_WSTRING | |
112 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void | |
113 | load(std::wstring &ws); | |
114 | #endif | |
115 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void | |
116 | load(char * t); | |
117 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void | |
118 | load(wchar_t * t); | |
119 | ||
120 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void | |
121 | init(); | |
122 | BOOST_ARCHIVE_OR_WARCHIVE_DECL | |
123 | basic_binary_iprimitive( | |
124 | std::basic_streambuf<Elem, Tr> & sb, | |
125 | bool no_codecvt | |
126 | ); | |
127 | BOOST_ARCHIVE_OR_WARCHIVE_DECL | |
128 | ~basic_binary_iprimitive(); | |
129 | public: | |
130 | // we provide an optimized load for all fundamental types | |
131 | // typedef serialization::is_bitwise_serializable<mpl::_1> | |
132 | // use_array_optimization; | |
133 | struct use_array_optimization { | |
134 | template <class T> | |
135 | #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS) | |
136 | struct apply { | |
137 | typedef typename boost::serialization::is_bitwise_serializable< T >::type type; | |
138 | }; | |
139 | #else | |
140 | struct apply : public boost::serialization::is_bitwise_serializable< T > {}; | |
141 | #endif | |
142 | }; | |
143 | ||
144 | // the optimized load_array dispatches to load_binary | |
145 | template <class ValueType> | |
146 | void load_array(serialization::array_wrapper<ValueType>& a, unsigned int) | |
147 | { | |
148 | load_binary(a.address(),a.count()*sizeof(ValueType)); | |
149 | } | |
150 | ||
151 | void | |
152 | load_binary(void *address, std::size_t count); | |
153 | }; | |
154 | ||
155 | template<class Archive, class Elem, class Tr> | |
156 | inline void | |
157 | basic_binary_iprimitive<Archive, Elem, Tr>::load_binary( | |
158 | void *address, | |
159 | std::size_t count | |
160 | ){ | |
161 | // note: an optimizer should eliminate the following for char files | |
162 | BOOST_ASSERT( | |
163 | static_cast<std::streamsize>(count / sizeof(Elem)) | |
164 | <= boost::integer_traits<std::streamsize>::const_max | |
165 | ); | |
166 | std::streamsize s = static_cast<std::streamsize>(count / sizeof(Elem)); | |
167 | std::streamsize scount = m_sb.sgetn( | |
168 | static_cast<Elem *>(address), | |
169 | s | |
170 | ); | |
171 | if(scount != s) | |
172 | boost::serialization::throw_exception( | |
173 | archive_exception(archive_exception::input_stream_error) | |
174 | ); | |
175 | // note: an optimizer should eliminate the following for char files | |
176 | BOOST_ASSERT(count % sizeof(Elem) <= boost::integer_traits<std::streamsize>::const_max); | |
177 | s = static_cast<std::streamsize>(count % sizeof(Elem)); | |
178 | if(0 < s){ | |
179 | // if(is.fail()) | |
180 | // boost::serialization::throw_exception( | |
181 | // archive_exception(archive_exception::stream_error) | |
182 | // ); | |
183 | Elem t; | |
184 | scount = m_sb.sgetn(& t, 1); | |
185 | if(scount != 1) | |
186 | boost::serialization::throw_exception( | |
187 | archive_exception(archive_exception::input_stream_error) | |
188 | ); | |
189 | std::memcpy(static_cast<char*>(address) + (count - s), &t, static_cast<std::size_t>(s)); | |
190 | } | |
191 | } | |
192 | ||
193 | } // namespace archive | |
194 | } // namespace boost | |
195 | ||
196 | #include <boost/archive/detail/abi_suffix.hpp> // pop pragmas | |
197 | ||
198 | #endif // BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP |