Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
1 #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
2 #define BOOST_ARCHIVE_OSERIALIZER_HPP
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 #pragma inline_depth(511)
8 #pragma inline_recursion(on)
11 #if defined(__MWERKS__)
12 #pragma inline_depth(511)
15 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
16 // oserializer.hpp: interface for serialization system.
18 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
19 // Use, modification and distribution is subject to the Boost Software
20 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
21 // http://www.boost.org/LICENSE_1_0.txt)
23 // See http://www.boost.org for updates, documentation, and revision history.
27 #include <boost/config.hpp>
28 #include <boost/detail/workaround.hpp>
29 #include <boost/throw_exception.hpp>
30 #include <boost/smart_cast.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/static_warning.hpp>
34 #include <boost/type_traits/is_pointer.hpp>
35 #include <boost/type_traits/is_fundamental.hpp>
36 #include <boost/type_traits/is_enum.hpp>
37 #include <boost/type_traits/is_volatile.hpp>
38 #include <boost/type_traits/is_const.hpp>
39 #include <boost/type_traits/is_same.hpp>
40 #include <boost/serialization/is_abstract.hpp>
42 #include <boost/mpl/eval_if.hpp>
43 #include <boost/mpl/and.hpp>
44 #include <boost/mpl/less.hpp>
45 #include <boost/mpl/greater_equal.hpp>
46 #include <boost/mpl/equal_to.hpp>
47 #include <boost/mpl/int.hpp>
48 #include <boost/mpl/identity.hpp>
49 #include <boost/mpl/list.hpp>
50 #include <boost/mpl/empty.hpp>
51 #include <boost/mpl/not.hpp>
53 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
54 #include <boost/serialization/extended_type_info_typeid.hpp>
56 // the following is need only for dynamic cast of polymorphic pointers
57 #include <boost/archive/detail/basic_oarchive.hpp>
58 #include <boost/archive/detail/basic_oserializer.hpp>
59 #include <boost/archive/detail/archive_pointer_oserializer.hpp>
61 #include <boost/serialization/force_include.hpp>
62 #include <boost/serialization/serialization.hpp>
63 #include <boost/serialization/version.hpp>
64 #include <boost/serialization/level.hpp>
65 #include <boost/serialization/tracking.hpp>
66 #include <boost/serialization/type_info_implementation.hpp>
67 #include <boost/serialization/nvp.hpp>
68 #include <boost/serialization/void_cast.hpp>
70 #include <boost/archive/archive_exception.hpp>
74 namespace serialization {
75 class extended_type_info;
76 } // namespace serialization
80 // an accessor to permit friend access to archives. Needed because
81 // some compilers don't handle friend templates completely
84 template<class Archive>
85 static void end_preamble(Archive & ar){
88 template<class Archive, class T>
89 static void save_primitive(Archive & ar, const T & t){
97 template<class Archive, class T>
98 class oserializer : public basic_oserializer
101 // private constructor to inhibit any existence other than the
103 explicit oserializer() :
105 * boost::serialization::type_info_implementation<T>::type::get_instance()
109 virtual BOOST_DLLEXPORT void save_object_data(
113 virtual bool class_info() const {
114 return boost::serialization::implementation_level<T>::value
115 >= boost::serialization::object_class_info;
117 virtual bool tracking(const unsigned int flags) const {
118 // if(0 != (flags & no_tracking))
120 return boost::serialization::tracking_level<T>::value == boost::serialization::track_always
121 || boost::serialization::tracking_level<T>::value == boost::serialization::track_selectivly
122 && serialized_as_pointer();
124 virtual unsigned int version() const {
125 return ::boost::serialization::version<T>::value;
127 virtual bool is_polymorphic() const {
128 typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation<
130 >::type::is_polymorphic::type typex;
133 static oserializer & instantiate(){
134 static oserializer instance;
137 virtual ~oserializer(){}
140 template<class Archive, class T>
141 BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
145 // make sure call is routed through the highest interface that might
146 // be specialized by the user.
147 boost::serialization::serialize_adl(
148 boost::smart_cast_reference<Archive &>(ar),
149 * static_cast<T *>(const_cast<void *>(x)),
154 // instantiation of this template creates a static object. Note inversion of
155 // normal argument order to workaround bizarre error in MSVC 6.0 which only
156 // manifests iftself during compiler time.
157 template<class T, class Archive>
158 class pointer_oserializer : public archive_pointer_oserializer<Archive>
161 virtual const basic_oserializer & get_basic_serializer() const {
162 return oserializer<Archive, T>::instantiate();
164 virtual BOOST_DLLEXPORT void save_object_ptr(
168 #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) )
171 // private constructor to inhibit any existence other than the
172 // static one. Note GCC doesn't permit constructor to be private
173 explicit BOOST_DLLEXPORT pointer_oserializer() BOOST_USED;
174 static const pointer_oserializer instance;
176 #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
177 // at least one compiler (CW) seems to require that serialize_adl
178 // be explicitly instantiated. Still under investigation.
179 void (* const m)(Archive &, T &, const unsigned);
180 boost::serialization::extended_type_info * (* e)();
182 static BOOST_DLLEXPORT const pointer_oserializer & instantiate() BOOST_USED;
183 virtual ~pointer_oserializer(){}
186 template<class T, class Archive>
187 BOOST_DLLEXPORT const pointer_oserializer<T, Archive> &
188 pointer_oserializer<T, Archive>::instantiate(){
192 // note: instances of this template to be constructed before the main
193 // is called in order for things to be initialized properly. For this
194 // reason, hiding the instance in a static function as was done above
195 // won't work here so we created a free instance here.
196 template<class T, class Archive>
197 const pointer_oserializer<T, Archive> pointer_oserializer<T, Archive>::instance;
199 template<class T, class Archive>
200 BOOST_DLLEXPORT void pointer_oserializer<T, Archive>::save_object_ptr(
205 // make sure call is routed through the highest interface that might
206 // be specialized by the user.
207 T * t = static_cast<T *>(const_cast<void *>(x));
208 const unsigned int file_version = boost::serialization::version<T>::value;
209 Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);
210 boost::serialization::save_construct_data_adl<Archive, T>(
215 ar_impl << boost::serialization::make_nvp(NULL, * t);
218 template<class T, class Archive>
219 #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
220 BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() :
221 archive_pointer_oserializer<Archive>(
222 * boost::serialization::type_info_implementation<T>::type::get_instance()
224 m(boost::serialization::serialize_adl<Archive, T>),
225 e(boost::serialization::type_info_implementation<T>::type::get_instance)
227 BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() :
228 archive_pointer_oserializer<Archive>(
229 * boost::serialization::type_info_implementation<T>::type::get_instance()
233 // make sure appropriate member function is instantiated
234 oserializer<Archive, T> & bos = oserializer<Archive, T>::instantiate();
238 template<class Archive, class T>
239 struct save_non_pointer_type {
240 // note this bounces the call right back to the archive
241 // with no runtime overhead
242 struct save_primitive {
243 static void invoke(Archive & ar, const T & t){
244 save_access::save_primitive(ar, t);
247 // same as above but passes through serialization
249 static void invoke(Archive & ar, const T & t){
250 // make sure call is routed through the highest interface that might
251 // be specialized by the user.
252 boost::serialization::serialize_adl(
255 ::boost::serialization::version<T>::value
259 // adds class information to the archive. This includes
260 // serialization level and class version
261 struct save_standard {
262 static void invoke(Archive &ar, const T & t){
263 ar.save_object(& t, oserializer<Archive, T>::instantiate());
267 // adds class information to the archive. This includes
268 // serialization level and class version
269 struct save_conditional {
270 static void invoke(Archive &ar, const T &t){
271 //if(0 == (ar.get_flags() & no_tracking))
272 save_standard::invoke(ar, t);
274 // save_only::invoke(ar, t);
279 BOOST_DEDUCED_TYPENAME mpl::eval_if<
282 boost::serialization::implementation_level<T>,
283 mpl::int_<boost::serialization::primitive_type>
285 mpl::identity<save_primitive>,
287 BOOST_DEDUCED_TYPENAME mpl::eval_if<
288 // class info / version
290 boost::serialization::implementation_level<T>,
291 mpl::int_<boost::serialization::object_class_info>
294 mpl::identity<save_standard>,
296 BOOST_DEDUCED_TYPENAME mpl::eval_if<
299 boost::serialization::tracking_level<T>,
300 mpl::int_<boost::serialization::track_never>
303 mpl::identity<save_only>,
305 // do a fast save only tracking is turned off
306 mpl::identity<save_conditional>
309 static void invoke(Archive & ar, const T & t){
310 // check that we're not trying to serialize something that
311 // has been marked not to be serialized. If this your program
312 // traps here, you've tried to serialize a class whose trait
313 // has been marked "non-serializable". Either reset the trait
314 // (see level.hpp) or change program not to serialize items of this class
315 BOOST_STATIC_ASSERT((
317 boost::serialization::implementation_level<T>,
318 mpl::int_<boost::serialization::primitive_type>
321 typex::invoke(ar, t);
325 template<class Archive, class TPtr>
326 struct save_pointer_type {
330 static const basic_pointer_oserializer * register_type(Archive & /* ar */){
331 // it has? to be polymorphic
333 boost::serialization::type_info_implementation<T>::type::is_polymorphic::value
335 return static_cast<const basic_pointer_oserializer *>(NULL);
342 static const basic_pointer_oserializer * register_type(Archive & ar){
343 return ar.register_type(static_cast<T *>(NULL));
348 static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
349 // there should never be any need to save an abstract polymorphic
350 // class pointer. Inhibiting code generation for this
351 // permits abstract base classes to be used - note: exception
352 // virtual serialize functions used for plug-ins
354 BOOST_DEDUCED_TYPENAME mpl::eval_if<
355 serialization::is_abstract<T>,
356 mpl::identity<abstract<T> >,
357 mpl::identity<non_abstract<T> >
359 return typex::register_type(ar);
363 struct non_polymorphic
368 const basic_pointer_oserializer * bpos_ptr
370 // save the requested pointer type
371 ar.save_pointer(& t, bpos_ptr);
381 const basic_pointer_oserializer * bpos_ptr
383 const boost::serialization::extended_type_info * this_type
384 = boost::serialization::type_info_implementation<T>::type::get_instance();
385 // retrieve the true type of the object pointed to
386 // if this assertion fails its an error in this library
387 assert(NULL != this_type);
388 const boost::serialization::extended_type_info * true_type
389 = boost::serialization::type_info_implementation<T>::type::get_derived_extended_type_info(t);
390 // note:if this exception is thrown, be sure that derived pointer
391 // is either regsitered or exported.
392 if(NULL == true_type){
393 boost::throw_exception(
394 archive_exception(archive_exception::unregistered_class)
398 // if its not a pointer to a more derived type
399 const void *vp = static_cast<const void *>(&t);
400 if(*this_type == *true_type){
401 ar.save_pointer(vp, bpos_ptr);
404 // convert pointer to more derived type. if this is thrown
405 // it means that the base/derived relationship hasn't be registered
406 vp = serialization::void_downcast(*true_type, *this_type, &t);
408 boost::throw_exception(
409 archive_exception(archive_exception::unregistered_cast)
413 // sice true_type is valid, and this only gets made if the
414 // pointer oserializer object has been created, this should never
416 bpos_ptr = archive_pointer_oserializer<Archive>::find(* true_type);
417 assert(NULL != bpos_ptr);
419 boost::throw_exception(
420 archive_exception(archive_exception::unregistered_class)
422 ar.save_pointer(vp, bpos_ptr);
430 const basic_pointer_oserializer * bpos_ptr
432 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
433 BOOST_DEDUCED_TYPENAME boost::serialization::
434 type_info_implementation<T>::type::is_polymorphic,
435 mpl::identity<polymorphic<T> >,
436 mpl::identity<non_polymorphic<T> >
438 typey::save(ar, const_cast<T &>(t), bpos_ptr);
442 static void const_check(T & t){
443 BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
446 static void invoke(Archive &ar, const TPtr t){
447 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
448 // if your program traps here, its because you tried to do
449 // something like ar << t where t is a pointer to a const value
450 // void f3(A const* a, text_oarchive& oa)
454 // with a compiler which doesn't support remove_const
457 // otherwise remove the const
459 const basic_pointer_oserializer * bpos_ptr = register_type(ar, * t);
461 basic_oarchive & boa = boost::smart_cast_reference<basic_oarchive &>(ar);
462 boa.save_null_pointer();
463 save_access::end_preamble(ar);
466 save(ar, * t, bpos_ptr);
470 template<class Archive, class T>
471 struct save_enum_type
473 static void invoke(Archive &ar, const T &t){
474 // convert enum to integers on save
475 const int i = static_cast<int>(t);
476 ar << boost::serialization::make_nvp(NULL, i);
480 template<class Archive, class T>
481 struct save_array_type
483 static void invoke(Archive &ar, const T &t){
484 save_access::end_preamble(ar);
485 // consider alignment
486 int count = sizeof(t) / (
487 static_cast<const char *>(static_cast<const void *>(&t[1]))
488 - static_cast<const char *>(static_cast<const void *>(&t[0]))
490 ar << BOOST_SERIALIZATION_NVP(count);
492 for(i = 0; i < count; ++i)
493 ar << boost::serialization::make_nvp("item", t[i]);
497 // note bogus arguments to workaround msvc 6 silent runtime failure
498 // declaration to satisfy gcc
499 template<class Archive, class T>
500 BOOST_DLLEXPORT const basic_pointer_oserializer &
501 instantiate_pointer_oserializer(
502 Archive * /* ar = NULL */,
506 template<class Archive, class T>
507 BOOST_DLLEXPORT const basic_pointer_oserializer &
508 instantiate_pointer_oserializer(
509 Archive * /* ar = NULL */,
512 // note: reversal of order of arguments to work around msvc 6.0 bug
513 // that manifests itself while trying to link.
514 return pointer_oserializer<T, Archive>::instantiate();
519 template<class Archive, class T>
520 inline void save(Archive & ar, const T &t){
522 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>,
523 mpl::identity<detail::save_pointer_type<Archive, T> >,
525 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>,
526 mpl::identity<detail::save_enum_type<Archive, T> >,
528 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>,
529 mpl::identity<detail::save_array_type<Archive, T> >,
531 mpl::identity<detail::save_non_pointer_type<Archive, T> >
535 typex::invoke(ar, t);
538 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
541 struct check_tracking {
542 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
543 // if its never tracked.
544 BOOST_DEDUCED_TYPENAME mpl::equal_to<
545 serialization::tracking_level<T>,
546 mpl::int_<serialization::track_never>
548 // it better not be a pointer
549 mpl::not_<is_pointer<T> >,
551 // otherwise if it might be tracked. So there shouldn't
552 // be any problem making a const
555 BOOST_STATIC_CONSTANT(bool, value = typex::value);
558 template<class Archive, class T>
559 inline void save(Archive & ar, T &t){
560 // if your program traps here, it indicates taht your doing one of the following:
561 // a) serializing an object of a type marked "track_never" through a pointer.
562 // b) saving an non-const object of a type not markd "track_never)
563 // Either of these conditions may be an indicator of an error usage of the
564 // serialization library and should be double checked. See documentation on
566 BOOST_STATIC_ASSERT(check_tracking<T>::value);
567 save(ar, const_cast<const T &>(t));
571 } // namespace archive
574 #endif // BOOST_ARCHIVE_OSERIALIZER_HPP