williamr@2
|
1 |
#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
|
williamr@2
|
2 |
#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
|
williamr@2
|
3 |
|
williamr@2
|
4 |
// MS compatible compilers support #pragma once
|
williamr@2
|
5 |
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
williamr@2
|
6 |
# pragma once
|
williamr@2
|
7 |
#pragma inline_depth(511)
|
williamr@2
|
8 |
#pragma inline_recursion(on)
|
williamr@2
|
9 |
#endif
|
williamr@2
|
10 |
|
williamr@2
|
11 |
#if defined(__MWERKS__)
|
williamr@2
|
12 |
#pragma inline_depth(511)
|
williamr@2
|
13 |
#endif
|
williamr@2
|
14 |
|
williamr@2
|
15 |
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
williamr@2
|
16 |
// iserializer.hpp: interface for serialization system.
|
williamr@2
|
17 |
|
williamr@2
|
18 |
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
williamr@2
|
19 |
// Use, modification and distribution is subject to the Boost Software
|
williamr@2
|
20 |
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
21 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
22 |
|
williamr@2
|
23 |
// See http://www.boost.org for updates, documentation, and revision history.
|
williamr@2
|
24 |
|
williamr@2
|
25 |
#include <new> // for placement new
|
williamr@2
|
26 |
#include <memory> // for auto_ptr
|
williamr@2
|
27 |
#include <cstddef> // size_t
|
williamr@2
|
28 |
|
williamr@2
|
29 |
#include <boost/config.hpp>
|
williamr@2
|
30 |
#include <boost/detail/workaround.hpp>
|
williamr@2
|
31 |
#if defined(BOOST_NO_STDC_NAMESPACE)
|
williamr@2
|
32 |
namespace std{
|
williamr@2
|
33 |
using ::size_t;
|
williamr@2
|
34 |
} // namespace std
|
williamr@2
|
35 |
#endif
|
williamr@2
|
36 |
#include <boost/throw_exception.hpp>
|
williamr@2
|
37 |
#include <boost/smart_cast.hpp>
|
williamr@2
|
38 |
#include <boost/static_assert.hpp>
|
williamr@2
|
39 |
#include <boost/static_warning.hpp>
|
williamr@2
|
40 |
#include <boost/detail/no_exceptions_support.hpp>
|
williamr@2
|
41 |
|
williamr@2
|
42 |
#include <boost/type_traits/is_pointer.hpp>
|
williamr@2
|
43 |
#include <boost/type_traits/is_fundamental.hpp>
|
williamr@2
|
44 |
#include <boost/type_traits/is_enum.hpp>
|
williamr@2
|
45 |
#include <boost/type_traits/is_const.hpp>
|
williamr@2
|
46 |
#include <boost/type_traits/remove_const.hpp>
|
williamr@2
|
47 |
#include <boost/serialization/is_abstract.hpp>
|
williamr@2
|
48 |
|
williamr@2
|
49 |
#include <boost/mpl/eval_if.hpp>
|
williamr@2
|
50 |
#include <boost/mpl/if.hpp>
|
williamr@2
|
51 |
#include <boost/mpl/identity.hpp>
|
williamr@2
|
52 |
#include <boost/mpl/or.hpp>
|
williamr@2
|
53 |
#include <boost/mpl/and.hpp>
|
williamr@2
|
54 |
#include <boost/mpl/less.hpp>
|
williamr@2
|
55 |
#include <boost/mpl/greater_equal.hpp>
|
williamr@2
|
56 |
#include <boost/mpl/int.hpp>
|
williamr@2
|
57 |
#include <boost/mpl/list.hpp>
|
williamr@2
|
58 |
#include <boost/mpl/empty.hpp>
|
williamr@2
|
59 |
#include <boost/mpl/not.hpp>
|
williamr@2
|
60 |
|
williamr@2
|
61 |
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
|
williamr@2
|
62 |
#include <boost/serialization/extended_type_info_typeid.hpp>
|
williamr@2
|
63 |
#endif
|
williamr@2
|
64 |
// the following is need only for dynamic cast of polymorphic pointers
|
williamr@2
|
65 |
#include <boost/archive/detail/basic_iarchive.hpp>
|
williamr@2
|
66 |
#include <boost/archive/detail/basic_iserializer.hpp>
|
williamr@2
|
67 |
#include <boost/archive/detail/archive_pointer_iserializer.hpp>
|
williamr@2
|
68 |
#include <boost/archive/archive_exception.hpp>
|
williamr@2
|
69 |
|
williamr@2
|
70 |
#include <boost/serialization/force_include.hpp>
|
williamr@2
|
71 |
#include <boost/serialization/serialization.hpp>
|
williamr@2
|
72 |
#include <boost/serialization/version.hpp>
|
williamr@2
|
73 |
#include <boost/serialization/level.hpp>
|
williamr@2
|
74 |
#include <boost/serialization/tracking.hpp>
|
williamr@2
|
75 |
#include <boost/serialization/type_info_implementation.hpp>
|
williamr@2
|
76 |
#include <boost/serialization/nvp.hpp>
|
williamr@2
|
77 |
#include <boost/serialization/binary_object.hpp>
|
williamr@2
|
78 |
#include <boost/serialization/void_cast.hpp>
|
williamr@2
|
79 |
|
williamr@2
|
80 |
namespace boost {
|
williamr@2
|
81 |
|
williamr@2
|
82 |
namespace serialization {
|
williamr@2
|
83 |
class extended_type_info;
|
williamr@2
|
84 |
} // namespace serialization
|
williamr@2
|
85 |
|
williamr@2
|
86 |
namespace archive {
|
williamr@2
|
87 |
|
williamr@2
|
88 |
// an accessor to permit friend access to archives. Needed because
|
williamr@2
|
89 |
// some compilers don't handle friend templates completely
|
williamr@2
|
90 |
class load_access {
|
williamr@2
|
91 |
public:
|
williamr@2
|
92 |
template<class Archive, class T>
|
williamr@2
|
93 |
static void load_primitive(Archive &ar, T &t){
|
williamr@2
|
94 |
ar.load(t);
|
williamr@2
|
95 |
}
|
williamr@2
|
96 |
};
|
williamr@2
|
97 |
|
williamr@2
|
98 |
namespace detail {
|
williamr@2
|
99 |
|
williamr@2
|
100 |
template<class Archive, class T>
|
williamr@2
|
101 |
class iserializer : public basic_iserializer
|
williamr@2
|
102 |
{
|
williamr@2
|
103 |
private:
|
williamr@2
|
104 |
virtual void destroy(/*const*/ void *address) const {
|
williamr@2
|
105 |
boost::serialization::access::destroy(static_cast<T *>(address));
|
williamr@2
|
106 |
}
|
williamr@2
|
107 |
// private constructor to inhibit any existence other than the
|
williamr@2
|
108 |
// static one
|
williamr@2
|
109 |
explicit iserializer() :
|
williamr@2
|
110 |
basic_iserializer(
|
williamr@2
|
111 |
* boost::serialization::type_info_implementation<T>::type::get_instance()
|
williamr@2
|
112 |
)
|
williamr@2
|
113 |
{}
|
williamr@2
|
114 |
public:
|
williamr@2
|
115 |
virtual BOOST_DLLEXPORT void load_object_data(
|
williamr@2
|
116 |
basic_iarchive & ar,
|
williamr@2
|
117 |
void *x,
|
williamr@2
|
118 |
const unsigned int file_version
|
williamr@2
|
119 |
) const BOOST_USED ;
|
williamr@2
|
120 |
virtual bool class_info() const {
|
williamr@2
|
121 |
return boost::serialization::implementation_level<T>::value
|
williamr@2
|
122 |
>= boost::serialization::object_class_info;
|
williamr@2
|
123 |
}
|
williamr@2
|
124 |
virtual bool tracking(const unsigned int flags) const {
|
williamr@2
|
125 |
// if(0 != (flags & no_tracking))
|
williamr@2
|
126 |
// return false;
|
williamr@2
|
127 |
return boost::serialization::tracking_level<T>::value
|
williamr@2
|
128 |
== boost::serialization::track_always
|
williamr@2
|
129 |
|| boost::serialization::tracking_level<T>::value
|
williamr@2
|
130 |
== boost::serialization::track_selectivly
|
williamr@2
|
131 |
&& serialized_as_pointer();
|
williamr@2
|
132 |
}
|
williamr@2
|
133 |
virtual unsigned int version() const {
|
williamr@2
|
134 |
return ::boost::serialization::version<T>::value;
|
williamr@2
|
135 |
}
|
williamr@2
|
136 |
virtual bool is_polymorphic() const {
|
williamr@2
|
137 |
typedef BOOST_DEDUCED_TYPENAME
|
williamr@2
|
138 |
boost::serialization::type_info_implementation<
|
williamr@2
|
139 |
T
|
williamr@2
|
140 |
>::type::is_polymorphic::type typex;
|
williamr@2
|
141 |
return typex::value;
|
williamr@2
|
142 |
}
|
williamr@2
|
143 |
static iserializer & instantiate(){
|
williamr@2
|
144 |
static iserializer instance;
|
williamr@2
|
145 |
return instance;
|
williamr@2
|
146 |
}
|
williamr@2
|
147 |
virtual ~iserializer(){};
|
williamr@2
|
148 |
};
|
williamr@2
|
149 |
|
williamr@2
|
150 |
template<class Archive, class T>
|
williamr@2
|
151 |
BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
|
williamr@2
|
152 |
basic_iarchive & ar,
|
williamr@2
|
153 |
void *x,
|
williamr@2
|
154 |
const unsigned int file_version
|
williamr@2
|
155 |
) const {
|
williamr@2
|
156 |
// make sure call is routed through the higest interface that might
|
williamr@2
|
157 |
// be specialized by the user.
|
williamr@2
|
158 |
boost::serialization::serialize_adl(
|
williamr@2
|
159 |
boost::smart_cast_reference<Archive &>(ar),
|
williamr@2
|
160 |
* static_cast<T *>(x),
|
williamr@2
|
161 |
file_version
|
williamr@2
|
162 |
);
|
williamr@2
|
163 |
}
|
williamr@2
|
164 |
|
williamr@2
|
165 |
// instantiation of this template creates a static object. Note inversion of
|
williamr@2
|
166 |
// normal argument order to workaround bizarre error in MSVC 6.0 which only
|
williamr@2
|
167 |
// manifests iftself during compiler time.
|
williamr@2
|
168 |
template<class T, class Archive>
|
williamr@2
|
169 |
class pointer_iserializer : public archive_pointer_iserializer<Archive>
|
williamr@2
|
170 |
{
|
williamr@2
|
171 |
private:
|
williamr@2
|
172 |
virtual const basic_iserializer & get_basic_serializer() const {
|
williamr@2
|
173 |
return iserializer<Archive, T>::instantiate();
|
williamr@2
|
174 |
}
|
williamr@2
|
175 |
virtual BOOST_DLLEXPORT void load_object_ptr(
|
williamr@2
|
176 |
basic_iarchive & ar,
|
williamr@2
|
177 |
void * & x,
|
williamr@2
|
178 |
const unsigned int file_version
|
williamr@2
|
179 |
) const BOOST_USED;
|
williamr@2
|
180 |
#if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) )
|
williamr@2
|
181 |
public:
|
williamr@2
|
182 |
#endif
|
williamr@2
|
183 |
// private constructor to inhibit any existence other than the
|
williamr@2
|
184 |
// static one. Note GCC doesn't permit constructor to be private
|
williamr@2
|
185 |
explicit BOOST_DLLEXPORT pointer_iserializer() BOOST_USED;
|
williamr@2
|
186 |
static const pointer_iserializer instance;
|
williamr@2
|
187 |
public:
|
williamr@2
|
188 |
// at least one compiler (CW) seems to require that serialize_adl
|
williamr@2
|
189 |
// be explicitly instantiated. Still under investigation.
|
williamr@2
|
190 |
#if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
williamr@2
|
191 |
void (* const m)(Archive &, T &, const unsigned);
|
williamr@2
|
192 |
boost::serialization::extended_type_info * (* e)();
|
williamr@2
|
193 |
#endif
|
williamr@2
|
194 |
static BOOST_DLLEXPORT const pointer_iserializer & instantiate() BOOST_USED;
|
williamr@2
|
195 |
virtual ~pointer_iserializer(){};
|
williamr@2
|
196 |
};
|
williamr@2
|
197 |
|
williamr@2
|
198 |
template<class T, class Archive>
|
williamr@2
|
199 |
BOOST_DLLEXPORT const pointer_iserializer<T, Archive> &
|
williamr@2
|
200 |
pointer_iserializer<T, Archive>::instantiate() {
|
williamr@2
|
201 |
return instance;
|
williamr@2
|
202 |
}
|
williamr@2
|
203 |
|
williamr@2
|
204 |
// note: instances of this template to be constructed before the main
|
williamr@2
|
205 |
// is called in order for things to be initialized properly. For this
|
williamr@2
|
206 |
// reason, hiding the instance in a static function as was done above
|
williamr@2
|
207 |
// won't work here so we created a free instance here.
|
williamr@2
|
208 |
template<class T, class Archive>
|
williamr@2
|
209 |
const pointer_iserializer<T, Archive> pointer_iserializer<T, Archive>::instance;
|
williamr@2
|
210 |
|
williamr@2
|
211 |
// note trick to be sure that operator new is using class specific
|
williamr@2
|
212 |
// version if such exists. Due to Peter Dimov.
|
williamr@2
|
213 |
// note: the following fails if T has no default constructor.
|
williamr@2
|
214 |
// otherwise it would have been ideal
|
williamr@2
|
215 |
//struct heap_allocator : public T
|
williamr@2
|
216 |
//{
|
williamr@2
|
217 |
// T * invoke(){
|
williamr@2
|
218 |
// return ::new(sizeof(T));
|
williamr@2
|
219 |
// }
|
williamr@2
|
220 |
//}
|
williamr@2
|
221 |
|
williamr@2
|
222 |
// note: this should really be a member of the load_ptr function
|
williamr@2
|
223 |
// below but some compilers still complain about this.
|
williamr@2
|
224 |
template<class T>
|
williamr@2
|
225 |
struct heap_allocator
|
williamr@2
|
226 |
{
|
williamr@2
|
227 |
#if 0
|
williamr@2
|
228 |
// note: this fails on msvc 7.0 and gcc 3.2
|
williamr@2
|
229 |
template <class U, U x> struct test;
|
williamr@2
|
230 |
typedef char* yes;
|
williamr@2
|
231 |
typedef int* no;
|
williamr@2
|
232 |
template <class U>
|
williamr@2
|
233 |
yes has_op_new(U*, test<void* (*)(std::size_t), &U::operator new>* = 0);
|
williamr@2
|
234 |
no has_op_new(...);
|
williamr@2
|
235 |
|
williamr@2
|
236 |
template<class U>
|
williamr@2
|
237 |
T * new_operator(U);
|
williamr@2
|
238 |
|
williamr@2
|
239 |
T * new_operator(yes){
|
williamr@2
|
240 |
return (T::operator new)(sizeof(T));
|
williamr@2
|
241 |
}
|
williamr@2
|
242 |
T * new_operator(no){
|
williamr@2
|
243 |
return static_cast<T *>(operator new(sizeof(T)));
|
williamr@2
|
244 |
}
|
williamr@2
|
245 |
static T * invoke(){
|
williamr@2
|
246 |
return new_operator(has_op_new(static_cast<T *>(NULL)));
|
williamr@2
|
247 |
}
|
williamr@2
|
248 |
#else
|
williamr@2
|
249 |
// while this doesn't handle operator new overload for class T
|
williamr@2
|
250 |
static T * invoke(){
|
williamr@2
|
251 |
return static_cast<T *>(operator new(sizeof(T)));
|
williamr@2
|
252 |
}
|
williamr@2
|
253 |
#endif
|
williamr@2
|
254 |
};
|
williamr@2
|
255 |
|
williamr@2
|
256 |
// due to Martin Ecker
|
williamr@2
|
257 |
template <typename T>
|
williamr@2
|
258 |
class auto_ptr_with_deleter
|
williamr@2
|
259 |
{
|
williamr@2
|
260 |
public:
|
williamr@2
|
261 |
explicit auto_ptr_with_deleter(T* p) :
|
williamr@2
|
262 |
m_p(p)
|
williamr@2
|
263 |
{}
|
williamr@2
|
264 |
~auto_ptr_with_deleter(){
|
williamr@2
|
265 |
if (m_p)
|
williamr@2
|
266 |
boost::serialization::access::destroy(m_p);
|
williamr@2
|
267 |
}
|
williamr@2
|
268 |
T* get() const {
|
williamr@2
|
269 |
return m_p;
|
williamr@2
|
270 |
}
|
williamr@2
|
271 |
|
williamr@2
|
272 |
T* release() {
|
williamr@2
|
273 |
T* p = m_p;
|
williamr@2
|
274 |
m_p = NULL;
|
williamr@2
|
275 |
return p;
|
williamr@2
|
276 |
}
|
williamr@2
|
277 |
private:
|
williamr@2
|
278 |
T* m_p;
|
williamr@2
|
279 |
};
|
williamr@2
|
280 |
|
williamr@2
|
281 |
template<class T, class Archive>
|
williamr@2
|
282 |
BOOST_DLLEXPORT void pointer_iserializer<T, Archive>::load_object_ptr(
|
williamr@2
|
283 |
basic_iarchive & ar,
|
williamr@2
|
284 |
void * & x,
|
williamr@2
|
285 |
const unsigned int file_version
|
williamr@2
|
286 |
) const {
|
williamr@2
|
287 |
Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);
|
williamr@2
|
288 |
|
williamr@2
|
289 |
// if(0 != (ar.get_flags() & no_object_creation)){
|
williamr@2
|
290 |
// ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(x));
|
williamr@2
|
291 |
// return;
|
williamr@2
|
292 |
// }
|
williamr@2
|
293 |
|
williamr@2
|
294 |
auto_ptr_with_deleter<T> ap(heap_allocator<T>::invoke());
|
williamr@2
|
295 |
if(NULL == ap.get())
|
williamr@2
|
296 |
boost::throw_exception(std::bad_alloc()) ;
|
williamr@2
|
297 |
|
williamr@2
|
298 |
T * t = ap.get();
|
williamr@2
|
299 |
x = t;
|
williamr@2
|
300 |
|
williamr@2
|
301 |
// catch exception during load_construct_data so that we don't
|
williamr@2
|
302 |
// automatically delete the t which is most likely not fully
|
williamr@2
|
303 |
// constructed
|
williamr@2
|
304 |
BOOST_TRY {
|
williamr@2
|
305 |
// this addresses an obscure situtation that occurs when
|
williamr@2
|
306 |
// load_constructor de-serializes something through a pointer.
|
williamr@2
|
307 |
ar.next_object_pointer(t);
|
williamr@2
|
308 |
boost::serialization::load_construct_data_adl<Archive, T>(
|
williamr@2
|
309 |
ar_impl,
|
williamr@2
|
310 |
t,
|
williamr@2
|
311 |
file_version
|
williamr@2
|
312 |
);
|
williamr@2
|
313 |
}
|
williamr@2
|
314 |
BOOST_CATCH(...){
|
williamr@2
|
315 |
BOOST_RETHROW;
|
williamr@2
|
316 |
}
|
williamr@2
|
317 |
BOOST_CATCH_END
|
williamr@2
|
318 |
|
williamr@2
|
319 |
ar_impl >> boost::serialization::make_nvp(NULL, * t);
|
williamr@2
|
320 |
ap.release();
|
williamr@2
|
321 |
}
|
williamr@2
|
322 |
|
williamr@2
|
323 |
template<class T, class Archive>
|
williamr@2
|
324 |
#if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
williamr@2
|
325 |
BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() :
|
williamr@2
|
326 |
archive_pointer_iserializer<Archive>(
|
williamr@2
|
327 |
* boost::serialization::type_info_implementation<T>::type::get_instance()
|
williamr@2
|
328 |
),
|
williamr@2
|
329 |
m(boost::serialization::serialize_adl<Archive, T>),
|
williamr@2
|
330 |
e(boost::serialization::type_info_implementation<T>::type::get_instance)
|
williamr@2
|
331 |
#else
|
williamr@2
|
332 |
BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() :
|
williamr@2
|
333 |
archive_pointer_iserializer<Archive>(
|
williamr@2
|
334 |
* boost::serialization::type_info_implementation<T>::type::get_instance()
|
williamr@2
|
335 |
)
|
williamr@2
|
336 |
#endif
|
williamr@2
|
337 |
{
|
williamr@2
|
338 |
iserializer<Archive, T> & bis = iserializer<Archive, T>::instantiate();
|
williamr@2
|
339 |
bis.set_bpis(this);
|
williamr@2
|
340 |
}
|
williamr@2
|
341 |
|
williamr@2
|
342 |
template<class Archive, class T>
|
williamr@2
|
343 |
struct load_non_pointer_type {
|
williamr@2
|
344 |
// note this bounces the call right back to the archive
|
williamr@2
|
345 |
// with no runtime overhead
|
williamr@2
|
346 |
struct load_primitive {
|
williamr@2
|
347 |
static void invoke(Archive & ar, T & t){
|
williamr@2
|
348 |
load_access::load_primitive(ar, t);
|
williamr@2
|
349 |
}
|
williamr@2
|
350 |
};
|
williamr@2
|
351 |
// note this bounces the call right back to the archive
|
williamr@2
|
352 |
// with no runtime overhead
|
williamr@2
|
353 |
struct load_only {
|
williamr@2
|
354 |
static void invoke(Archive & ar, T & t){
|
williamr@2
|
355 |
// short cut to user's serializer
|
williamr@2
|
356 |
// make sure call is routed through the higest interface that might
|
williamr@2
|
357 |
// be specialized by the user.
|
williamr@2
|
358 |
boost::serialization::serialize_adl(
|
williamr@2
|
359 |
ar, t, boost::serialization::version<T>::value
|
williamr@2
|
360 |
);
|
williamr@2
|
361 |
}
|
williamr@2
|
362 |
};
|
williamr@2
|
363 |
|
williamr@2
|
364 |
// note this save class information including version
|
williamr@2
|
365 |
// and serialization level to the archive
|
williamr@2
|
366 |
struct load_standard {
|
williamr@2
|
367 |
static void invoke(Archive &ar, T &t){
|
williamr@2
|
368 |
//BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
|
williamr@2
|
369 |
// borland - for some reason T is const here - even though
|
williamr@2
|
370 |
// its not called that way - so fix it her
|
williamr@2
|
371 |
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex;
|
williamr@2
|
372 |
void * x = & const_cast<typex &>(t);
|
williamr@2
|
373 |
ar.load_object(x, iserializer<Archive, T>::instantiate());
|
williamr@2
|
374 |
}
|
williamr@2
|
375 |
};
|
williamr@2
|
376 |
|
williamr@2
|
377 |
struct load_conditional {
|
williamr@2
|
378 |
static void invoke(Archive &ar, T &t){
|
williamr@2
|
379 |
//if(0 == (ar.get_flags() & no_tracking))
|
williamr@2
|
380 |
load_standard::invoke(ar, t);
|
williamr@2
|
381 |
//else
|
williamr@2
|
382 |
// load_only::invoke(ar, t);
|
williamr@2
|
383 |
}
|
williamr@2
|
384 |
};
|
williamr@2
|
385 |
|
williamr@2
|
386 |
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
williamr@2
|
387 |
// if its primitive
|
williamr@2
|
388 |
mpl::equal_to<
|
williamr@2
|
389 |
boost::serialization::implementation_level<T>,
|
williamr@2
|
390 |
mpl::int_<boost::serialization::primitive_type>
|
williamr@2
|
391 |
>,
|
williamr@2
|
392 |
mpl::identity<load_primitive>,
|
williamr@2
|
393 |
// else
|
williamr@2
|
394 |
BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
williamr@2
|
395 |
// class info / version
|
williamr@2
|
396 |
mpl::greater_equal<
|
williamr@2
|
397 |
boost::serialization::implementation_level<T>,
|
williamr@2
|
398 |
mpl::int_<boost::serialization::object_class_info>
|
williamr@2
|
399 |
>,
|
williamr@2
|
400 |
// do standard load
|
williamr@2
|
401 |
mpl::identity<load_standard>,
|
williamr@2
|
402 |
// else
|
williamr@2
|
403 |
BOOST_DEDUCED_TYPENAME mpl::eval_if<
|
williamr@2
|
404 |
// no tracking
|
williamr@2
|
405 |
mpl::equal_to<
|
williamr@2
|
406 |
boost::serialization::tracking_level<T>,
|
williamr@2
|
407 |
mpl::int_<boost::serialization::track_never>
|
williamr@2
|
408 |
>,
|
williamr@2
|
409 |
// do a fast load
|
williamr@2
|
410 |
mpl::identity<load_only>,
|
williamr@2
|
411 |
// else
|
williamr@2
|
412 |
// do a fast load only tracking is turned off
|
williamr@2
|
413 |
mpl::identity<load_conditional>
|
williamr@2
|
414 |
> > >::type typex;
|
williamr@2
|
415 |
|
williamr@2
|
416 |
static void invoke(Archive & ar, T &t){
|
williamr@2
|
417 |
BOOST_STATIC_ASSERT((
|
williamr@2
|
418 |
mpl::greater_equal<
|
williamr@2
|
419 |
boost::serialization::implementation_level<T>,
|
williamr@2
|
420 |
mpl::int_<boost::serialization::primitive_type>
|
williamr@2
|
421 |
>::value
|
williamr@2
|
422 |
));
|
williamr@2
|
423 |
typex::invoke(ar, t);
|
williamr@2
|
424 |
}
|
williamr@2
|
425 |
};
|
williamr@2
|
426 |
|
williamr@2
|
427 |
template<class Archive, class Tptr>
|
williamr@2
|
428 |
struct load_pointer_type {
|
williamr@2
|
429 |
template<class T>
|
williamr@2
|
430 |
struct abstract
|
williamr@2
|
431 |
{
|
williamr@2
|
432 |
static const basic_pointer_iserializer * register_type(Archive & /* ar */){
|
williamr@2
|
433 |
#if ! defined(__BORLANDC__)
|
williamr@2
|
434 |
typedef BOOST_DEDUCED_TYPENAME
|
williamr@2
|
435 |
boost::serialization::type_info_implementation<T>::type::is_polymorphic typex;
|
williamr@2
|
436 |
// it has? to be polymorphic
|
williamr@2
|
437 |
BOOST_STATIC_ASSERT(typex::value);
|
williamr@2
|
438 |
#endif
|
williamr@2
|
439 |
return static_cast<basic_pointer_iserializer *>(NULL);
|
williamr@2
|
440 |
}
|
williamr@2
|
441 |
};
|
williamr@2
|
442 |
|
williamr@2
|
443 |
template<class T>
|
williamr@2
|
444 |
struct non_abstract
|
williamr@2
|
445 |
{
|
williamr@2
|
446 |
static const basic_pointer_iserializer * register_type(Archive & ar){
|
williamr@2
|
447 |
return ar.register_type(static_cast<T *>(NULL));
|
williamr@2
|
448 |
}
|
williamr@2
|
449 |
};
|
williamr@2
|
450 |
|
williamr@2
|
451 |
template<class T>
|
williamr@2
|
452 |
static const basic_pointer_iserializer * register_type(Archive &ar, T & /*t*/){
|
williamr@2
|
453 |
// there should never be any need to load an abstract polymorphic
|
williamr@2
|
454 |
// class pointer. Inhibiting code generation for this
|
williamr@2
|
455 |
// permits abstract base classes to be used - note: exception
|
williamr@2
|
456 |
// virtual serialize functions used for plug-ins
|
williamr@2
|
457 |
typedef BOOST_DEDUCED_TYPENAME
|
williamr@2
|
458 |
mpl::eval_if<
|
williamr@2
|
459 |
serialization::is_abstract<T>,
|
williamr@2
|
460 |
mpl::identity<abstract<T> >,
|
williamr@2
|
461 |
mpl::identity<non_abstract<T> >
|
williamr@2
|
462 |
>::type typex;
|
williamr@2
|
463 |
return typex::register_type(ar);
|
williamr@2
|
464 |
}
|
williamr@2
|
465 |
|
williamr@2
|
466 |
template<class T>
|
williamr@2
|
467 |
static T * pointer_tweak(
|
williamr@2
|
468 |
const boost::serialization::extended_type_info & eti,
|
williamr@2
|
469 |
void * t,
|
williamr@2
|
470 |
T &
|
williamr@2
|
471 |
) {
|
williamr@2
|
472 |
// tweak the pointer back to the base class
|
williamr@2
|
473 |
return static_cast<T *>(
|
williamr@2
|
474 |
boost::serialization::void_upcast(
|
williamr@2
|
475 |
eti,
|
williamr@2
|
476 |
* boost::serialization::type_info_implementation<T>::type::get_instance(),
|
williamr@2
|
477 |
t
|
williamr@2
|
478 |
)
|
williamr@2
|
479 |
);
|
williamr@2
|
480 |
}
|
williamr@2
|
481 |
|
williamr@2
|
482 |
static void invoke(Archive & ar, Tptr & t){
|
williamr@2
|
483 |
const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
|
williamr@2
|
484 |
const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
|
williamr@2
|
485 |
* reinterpret_cast<void **>(&t),
|
williamr@2
|
486 |
bpis_ptr,
|
williamr@2
|
487 |
archive_pointer_iserializer<Archive>::find
|
williamr@2
|
488 |
);
|
williamr@2
|
489 |
// if the pointer isn't that of the base class
|
williamr@2
|
490 |
if(newbpis_ptr != bpis_ptr){
|
williamr@2
|
491 |
t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
|
williamr@2
|
492 |
}
|
williamr@2
|
493 |
}
|
williamr@2
|
494 |
};
|
williamr@2
|
495 |
|
williamr@2
|
496 |
template<class Archive, class T>
|
williamr@2
|
497 |
struct load_enum_type {
|
williamr@2
|
498 |
static void invoke(Archive &ar, T &t){
|
williamr@2
|
499 |
// convert integers to correct enum to load
|
williamr@2
|
500 |
int i;
|
williamr@2
|
501 |
ar >> boost::serialization::make_nvp(NULL, i);
|
williamr@2
|
502 |
t = static_cast<T>(i);
|
williamr@2
|
503 |
}
|
williamr@2
|
504 |
};
|
williamr@2
|
505 |
|
williamr@2
|
506 |
template<class Archive, class T>
|
williamr@2
|
507 |
struct load_array_type {
|
williamr@2
|
508 |
static void invoke(Archive &ar, T &t){
|
williamr@2
|
509 |
// convert integers to correct enum to load
|
williamr@2
|
510 |
int current_count = sizeof(t) / (
|
williamr@2
|
511 |
static_cast<char *>(static_cast<void *>(&t[1]))
|
williamr@2
|
512 |
- static_cast<char *>(static_cast<void *>(&t[0]))
|
williamr@2
|
513 |
);
|
williamr@2
|
514 |
int count;
|
williamr@2
|
515 |
ar >> BOOST_SERIALIZATION_NVP(count);
|
williamr@2
|
516 |
if(count > current_count)
|
williamr@2
|
517 |
boost::throw_exception(archive::archive_exception(
|
williamr@2
|
518 |
boost::archive::archive_exception::array_size_too_short
|
williamr@2
|
519 |
));
|
williamr@2
|
520 |
int i;
|
williamr@2
|
521 |
for(i = 0; i < count; ++i)
|
williamr@2
|
522 |
ar >> boost::serialization::make_nvp("item", t[i]);
|
williamr@2
|
523 |
}
|
williamr@2
|
524 |
};
|
williamr@2
|
525 |
|
williamr@2
|
526 |
// note bogus arguments to workaround msvc 6 silent runtime failure
|
williamr@2
|
527 |
template<class Archive, class T>
|
williamr@2
|
528 |
BOOST_DLLEXPORT
|
williamr@2
|
529 |
inline const basic_pointer_iserializer &
|
williamr@2
|
530 |
instantiate_pointer_iserializer(
|
williamr@2
|
531 |
Archive * /* ar = NULL */,
|
williamr@2
|
532 |
T * /* t = NULL */
|
williamr@2
|
533 |
) BOOST_USED;
|
williamr@2
|
534 |
|
williamr@2
|
535 |
template<class Archive, class T>
|
williamr@2
|
536 |
BOOST_DLLEXPORT
|
williamr@2
|
537 |
inline const basic_pointer_iserializer &
|
williamr@2
|
538 |
instantiate_pointer_iserializer(
|
williamr@2
|
539 |
Archive * /* ar = NULL */,
|
williamr@2
|
540 |
T * /* t = NULL */
|
williamr@2
|
541 |
){
|
williamr@2
|
542 |
// note: reversal of order of arguments to work around msvc 6.0 bug
|
williamr@2
|
543 |
// that manifests itself while trying to link.
|
williamr@2
|
544 |
return pointer_iserializer<T, Archive>::instantiate();
|
williamr@2
|
545 |
}
|
williamr@2
|
546 |
|
williamr@2
|
547 |
} // detail
|
williamr@2
|
548 |
|
williamr@2
|
549 |
template<class Archive, class T>
|
williamr@2
|
550 |
inline void load(Archive &ar, T &t){
|
williamr@2
|
551 |
// if this assertion trips. It means we're trying to load a
|
williamr@2
|
552 |
// const object with a compiler that doesn't have correct
|
williamr@2
|
553 |
// funtion template ordering. On other compilers, this is
|
williamr@2
|
554 |
// handled below.
|
williamr@2
|
555 |
BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
|
williamr@2
|
556 |
typedef
|
williamr@2
|
557 |
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>,
|
williamr@2
|
558 |
mpl::identity<detail::load_pointer_type<Archive, T> >
|
williamr@2
|
559 |
,//else
|
williamr@2
|
560 |
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>,
|
williamr@2
|
561 |
mpl::identity<detail::load_array_type<Archive, T> >
|
williamr@2
|
562 |
,//else
|
williamr@2
|
563 |
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>,
|
williamr@2
|
564 |
mpl::identity<detail::load_enum_type<Archive, T> >
|
williamr@2
|
565 |
,//else
|
williamr@2
|
566 |
mpl::identity<detail::load_non_pointer_type<Archive, T> >
|
williamr@2
|
567 |
>
|
williamr@2
|
568 |
>
|
williamr@2
|
569 |
>::type typex;
|
williamr@2
|
570 |
typex::invoke(ar, t);
|
williamr@2
|
571 |
}
|
williamr@2
|
572 |
|
williamr@2
|
573 |
// BORLAND
|
williamr@2
|
574 |
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
|
williamr@2
|
575 |
// borland has a couple fo problems
|
williamr@2
|
576 |
// a) if function is partiall specialized - see below
|
williamr@2
|
577 |
// const paramters are transformed to non-const ones
|
williamr@2
|
578 |
// b) implementation of base_object can't be made to work
|
williamr@2
|
579 |
// correctly which results in all base_object s being const.
|
williamr@2
|
580 |
// So, strip off the const for borland. This breaks the trap
|
williamr@2
|
581 |
// for loading const objects - but I see no alternative
|
williamr@2
|
582 |
template<class Archive, class T>
|
williamr@2
|
583 |
inline void load(Archive &ar, const T & t){
|
williamr@2
|
584 |
load(ar, const_cast<T &>(t));
|
williamr@2
|
585 |
}
|
williamr@2
|
586 |
#endif
|
williamr@2
|
587 |
|
williamr@2
|
588 |
// let wrappers through. (Someday implement is_wrapper)
|
williamr@2
|
589 |
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
williamr@2
|
590 |
template<class Archive, class T>
|
williamr@2
|
591 |
inline void load(Archive &ar, const serialization::nvp<T> &t){
|
williamr@2
|
592 |
boost::archive::load(ar, const_cast<serialization::nvp<T> &>(t));
|
williamr@2
|
593 |
}
|
williamr@2
|
594 |
template<class Archive>
|
williamr@2
|
595 |
inline void load(Archive &ar, const serialization::binary_object &t){
|
williamr@2
|
596 |
boost::archive::load(ar, const_cast<serialization::binary_object &>(t));
|
williamr@2
|
597 |
}
|
williamr@2
|
598 |
|
williamr@2
|
599 |
//template<class Archive, class T>
|
williamr@2
|
600 |
//inline void load(Archive &ar, const serialization::binary_object &t){
|
williamr@2
|
601 |
// load(ar, const_cast<binary_object &>(t));
|
williamr@2
|
602 |
//}
|
williamr@2
|
603 |
#endif
|
williamr@2
|
604 |
|
williamr@2
|
605 |
} // namespace archive
|
williamr@2
|
606 |
} // namespace boost
|
williamr@2
|
607 |
|
williamr@2
|
608 |
#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
|