~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to boost/archive/detail/oserializer.hpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
 
2
#define BOOST_ARCHIVE_OSERIALIZER_HPP
 
3
 
 
4
// MS compatible compilers support #pragma once
 
5
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 
6
# pragma once
 
7
#pragma inline_depth(511)
 
8
#pragma inline_recursion(on)
 
9
#endif
 
10
 
 
11
#if defined(__MWERKS__)
 
12
#pragma inline_depth(511)
 
13
#endif
 
14
 
 
15
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
 
16
// oserializer.hpp: interface for serialization system.
 
17
 
 
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)
 
22
 
 
23
//  See http://www.boost.org for updates, documentation, and revision history.
 
24
 
 
25
#include <boost/assert.hpp>
 
26
#include <cstddef> // NULL
 
27
 
 
28
#include <boost/config.hpp>
 
29
#include <boost/static_assert.hpp>
 
30
#include <boost/detail/workaround.hpp>
 
31
 
 
32
#include <boost/mpl/eval_if.hpp>
 
33
#include <boost/mpl/equal_to.hpp>
 
34
#include <boost/mpl/greater_equal.hpp>
 
35
#include <boost/mpl/identity.hpp>
 
36
 
 
37
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
 
38
    #include <boost/serialization/extended_type_info_typeid.hpp>   
 
39
#endif
 
40
#include <boost/serialization/throw_exception.hpp>
 
41
#include <boost/serialization/smart_cast.hpp>
 
42
#include <boost/serialization/assume_abstract.hpp>
 
43
#include <boost/serialization/static_warning.hpp>
 
44
 
 
45
#include <boost/type_traits/is_pointer.hpp>
 
46
#include <boost/type_traits/is_enum.hpp>
 
47
#include <boost/type_traits/is_const.hpp>
 
48
#include <boost/type_traits/is_polymorphic.hpp>
 
49
#include <boost/type_traits/remove_extent.hpp>
 
50
 
 
51
#include <boost/serialization/serialization.hpp>
 
52
#include <boost/serialization/version.hpp>
 
53
#include <boost/serialization/level.hpp>
 
54
#include <boost/serialization/tracking.hpp>
 
55
#include <boost/serialization/type_info_implementation.hpp>
 
56
#include <boost/serialization/nvp.hpp>
 
57
#include <boost/serialization/void_cast.hpp>
 
58
#include <boost/serialization/array.hpp>
 
59
#include <boost/serialization/collection_size_type.hpp>
 
60
#include <boost/serialization/singleton.hpp>
 
61
 
 
62
#include <boost/archive/archive_exception.hpp>
 
63
#include <boost/archive/detail/basic_oarchive.hpp>
 
64
#include <boost/archive/detail/basic_oserializer.hpp>
 
65
#include <boost/archive/detail/basic_pointer_oserializer.hpp>
 
66
#include <boost/archive/detail/archive_serializer_map.hpp>
 
67
#include <boost/archive/detail/check.hpp>
 
68
 
 
69
namespace boost {
 
70
 
 
71
namespace serialization {
 
72
    class extended_type_info;
 
73
} // namespace serialization
 
74
 
 
75
namespace archive {
 
76
 
 
77
// an accessor to permit friend access to archives.  Needed because
 
78
// some compilers don't handle friend templates completely
 
79
class save_access {
 
80
public:
 
81
    template<class Archive>
 
82
    static void end_preamble(Archive & ar){
 
83
        ar.end_preamble();
 
84
    }
 
85
    template<class Archive, class T>
 
86
    static void save_primitive(Archive & ar, const  T & t){
 
87
        ar.end_preamble();
 
88
        ar.save(t);
 
89
    }
 
90
};
 
91
 
 
92
namespace detail {
 
93
 
 
94
#ifdef BOOST_MSVC
 
95
#  pragma warning(push)
 
96
#  pragma warning(disable : 4511 4512)
 
97
#endif
 
98
 
 
99
template<class Archive, class T>
 
100
class oserializer : public basic_oserializer
 
101
{
 
102
private:
 
103
    // private constructor to inhibit any existence other than the 
 
104
    // static one
 
105
public:
 
106
    explicit BOOST_DLLEXPORT oserializer() :
 
107
        basic_oserializer(
 
108
            boost::serialization::singleton<
 
109
                BOOST_DEDUCED_TYPENAME 
 
110
                boost::serialization::type_info_implementation< T >::type
 
111
            >::get_const_instance()
 
112
        )
 
113
    {}
 
114
    virtual BOOST_DLLEXPORT void save_object_data(
 
115
        basic_oarchive & ar,    
 
116
        const void *x
 
117
    ) const BOOST_USED;
 
118
    virtual bool class_info() const {
 
119
        return boost::serialization::implementation_level< T >::value 
 
120
            >= boost::serialization::object_class_info;
 
121
    }
 
122
    virtual bool tracking(const unsigned int /* flags */) const {
 
123
        return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
 
124
            || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
 
125
                && serialized_as_pointer());
 
126
    }
 
127
    virtual version_type version() const {
 
128
        return version_type(::boost::serialization::version< T >::value);
 
129
    }
 
130
    virtual bool is_polymorphic() const {
 
131
        return boost::is_polymorphic< T >::value;
 
132
    }
 
133
    virtual ~oserializer(){}
 
134
};
 
135
 
 
136
#ifdef BOOST_MSVC
 
137
#  pragma warning(pop)
 
138
#endif
 
139
 
 
140
template<class Archive, class T>
 
141
BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
 
142
    basic_oarchive & ar,    
 
143
    const void *x
 
144
) const {
 
145
    // make sure call is routed through the highest interface that might
 
146
    // be specialized by the user.
 
147
    BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
 
148
    boost::serialization::serialize_adl(
 
149
        boost::serialization::smart_cast_reference<Archive &>(ar),
 
150
        * static_cast<T *>(const_cast<void *>(x)),
 
151
        version()
 
152
    );
 
153
}
 
154
 
 
155
#ifdef BOOST_MSVC
 
156
#  pragma warning(push)
 
157
#  pragma warning(disable : 4511 4512)
 
158
#endif
 
159
 
 
160
template<class Archive, class T>
 
161
class pointer_oserializer :
 
162
    public basic_pointer_oserializer
 
163
{
 
164
private:
 
165
    const basic_oserializer & 
 
166
    get_basic_serializer() const {
 
167
        return boost::serialization::singleton<
 
168
            oserializer<Archive, T>
 
169
        >::get_const_instance();
 
170
    }
 
171
    virtual BOOST_DLLEXPORT void save_object_ptr(
 
172
        basic_oarchive & ar,
 
173
        const void * x
 
174
    ) const BOOST_USED;
 
175
public:
 
176
    pointer_oserializer();
 
177
    ~pointer_oserializer();
 
178
};
 
179
 
 
180
#ifdef BOOST_MSVC
 
181
#  pragma warning(pop)
 
182
#endif
 
183
 
 
184
template<class Archive, class T>
 
185
BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
 
186
    basic_oarchive & ar,
 
187
    const void * x
 
188
) const {
 
189
    BOOST_ASSERT(NULL != x);
 
190
    // make sure call is routed through the highest interface that might
 
191
    // be specialized by the user.
 
192
    T * t = static_cast<T *>(const_cast<void *>(x));
 
193
    const unsigned int file_version = boost::serialization::version< T >::value;
 
194
    Archive & ar_impl 
 
195
        = boost::serialization::smart_cast_reference<Archive &>(ar);
 
196
    boost::serialization::save_construct_data_adl<Archive, T>(
 
197
        ar_impl, 
 
198
        t, 
 
199
        file_version
 
200
    );
 
201
    ar_impl << boost::serialization::make_nvp(NULL, * t);
 
202
}
 
203
 
 
204
template<class Archive, class T>
 
205
pointer_oserializer<Archive, T>::pointer_oserializer() :
 
206
    basic_pointer_oserializer(
 
207
        boost::serialization::singleton<
 
208
            BOOST_DEDUCED_TYPENAME 
 
209
            boost::serialization::type_info_implementation< T >::type
 
210
        >::get_const_instance()
 
211
    )
 
212
{
 
213
    // make sure appropriate member function is instantiated
 
214
    boost::serialization::singleton<
 
215
        oserializer<Archive, T> 
 
216
    >::get_mutable_instance().set_bpos(this);
 
217
    archive_serializer_map<Archive>::insert(this);
 
218
}
 
219
 
 
220
template<class Archive, class T>
 
221
pointer_oserializer<Archive, T>::~pointer_oserializer(){
 
222
    archive_serializer_map<Archive>::erase(this);
 
223
}
 
224
 
 
225
template<class Archive>
 
226
struct save_non_pointer_type {
 
227
    // note this bounces the call right back to the archive
 
228
    // with no runtime overhead
 
229
    struct save_primitive {
 
230
        template<class T>
 
231
        static void invoke(Archive & ar, const T & t){
 
232
            save_access::save_primitive(ar, t);
 
233
        }
 
234
    };
 
235
    // same as above but passes through serialization
 
236
    struct save_only {
 
237
        template<class T>
 
238
        static void invoke(Archive & ar, const T & t){
 
239
            // make sure call is routed through the highest interface that might
 
240
            // be specialized by the user.
 
241
            boost::serialization::serialize_adl(
 
242
                ar, 
 
243
                const_cast<T &>(t), 
 
244
                ::boost::serialization::version< T >::value
 
245
            );
 
246
        }
 
247
    };
 
248
    // adds class information to the archive. This includes
 
249
    // serialization level and class version
 
250
    struct save_standard {
 
251
        template<class T>
 
252
        static void invoke(Archive &ar, const T & t){
 
253
            ar.save_object(
 
254
                & t, 
 
255
                boost::serialization::singleton<
 
256
                    oserializer<Archive, T>
 
257
                >::get_const_instance()
 
258
            );
 
259
        }
 
260
    };
 
261
 
 
262
    // adds class information to the archive. This includes
 
263
    // serialization level and class version
 
264
    struct save_conditional {
 
265
        template<class T>
 
266
        static void invoke(Archive &ar, const T &t){
 
267
            //if(0 == (ar.get_flags() & no_tracking))
 
268
                save_standard::invoke(ar, t);
 
269
            //else
 
270
            //   save_only::invoke(ar, t);
 
271
        }
 
272
    };
 
273
 
 
274
 
 
275
    template<class T>
 
276
    static void invoke(Archive & ar, const T & t){
 
277
        typedef 
 
278
            BOOST_DEDUCED_TYPENAME mpl::eval_if<
 
279
            // if its primitive
 
280
                mpl::equal_to<
 
281
                    boost::serialization::implementation_level< T >,
 
282
                    mpl::int_<boost::serialization::primitive_type>
 
283
                >,
 
284
                mpl::identity<save_primitive>,
 
285
            // else
 
286
            BOOST_DEDUCED_TYPENAME mpl::eval_if<
 
287
                // class info / version
 
288
                mpl::greater_equal<
 
289
                    boost::serialization::implementation_level< T >,
 
290
                    mpl::int_<boost::serialization::object_class_info>
 
291
                >,
 
292
                // do standard save
 
293
                mpl::identity<save_standard>,
 
294
            // else
 
295
            BOOST_DEDUCED_TYPENAME mpl::eval_if<
 
296
                    // no tracking
 
297
                mpl::equal_to<
 
298
                    boost::serialization::tracking_level< T >,
 
299
                    mpl::int_<boost::serialization::track_never>
 
300
                >,
 
301
                // do a fast save
 
302
                mpl::identity<save_only>,
 
303
            // else
 
304
                // do a fast save only tracking is turned off
 
305
                mpl::identity<save_conditional>
 
306
            > > >::type typex; 
 
307
        check_object_versioning< T >();
 
308
        typex::invoke(ar, t);
 
309
    }
 
310
    template<class T>
 
311
    static void invoke(Archive & ar, T & t){
 
312
        check_object_level< T >();
 
313
        check_object_tracking< T >();
 
314
        invoke(ar, const_cast<const T &>(t));
 
315
    }
 
316
};
 
317
 
 
318
template<class Archive>
 
319
struct save_pointer_type {
 
320
    struct abstract
 
321
    {
 
322
        template<class T>
 
323
        static const basic_pointer_oserializer * register_type(Archive & /* ar */){
 
324
            // it has? to be polymorphic
 
325
            BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
 
326
            return NULL;
 
327
        }
 
328
    };
 
329
 
 
330
    struct non_abstract
 
331
    {
 
332
        template<class T>
 
333
        static const basic_pointer_oserializer * register_type(Archive & ar){
 
334
            return ar.register_type(static_cast<T *>(NULL));
 
335
        }
 
336
    };
 
337
 
 
338
    template<class T>
 
339
    static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
 
340
        // there should never be any need to save an abstract polymorphic 
 
341
        // class pointer.  Inhibiting code generation for this
 
342
        // permits abstract base classes to be used - note: exception
 
343
        // virtual serialize functions used for plug-ins
 
344
        typedef 
 
345
            BOOST_DEDUCED_TYPENAME mpl::eval_if<
 
346
                boost::serialization::is_abstract< T >,
 
347
                mpl::identity<abstract>,
 
348
                mpl::identity<non_abstract>       
 
349
            >::type typex;
 
350
        return typex::template register_type< T >(ar);
 
351
    }
 
352
 
 
353
    struct non_polymorphic
 
354
    {
 
355
        template<class T>
 
356
        static void save(
 
357
            Archive &ar, 
 
358
            T & t
 
359
        ){
 
360
            const basic_pointer_oserializer & bpos = 
 
361
                boost::serialization::singleton<
 
362
                    pointer_oserializer<Archive, T>
 
363
                >::get_const_instance();
 
364
            // save the requested pointer type
 
365
            ar.save_pointer(& t, & bpos);
 
366
        }
 
367
    };
 
368
 
 
369
    struct polymorphic
 
370
    {
 
371
        template<class T>
 
372
        static void save(
 
373
            Archive &ar, 
 
374
            T & t
 
375
        ){
 
376
            BOOST_DEDUCED_TYPENAME 
 
377
            boost::serialization::type_info_implementation< T >::type const
 
378
            & i = boost::serialization::singleton<
 
379
                BOOST_DEDUCED_TYPENAME 
 
380
                boost::serialization::type_info_implementation< T >::type
 
381
            >::get_const_instance();
 
382
 
 
383
            boost::serialization::extended_type_info const * const this_type = & i;
 
384
 
 
385
            // retrieve the true type of the object pointed to
 
386
            // if this assertion fails its an error in this library
 
387
            BOOST_ASSERT(NULL != this_type);
 
388
 
 
389
            const boost::serialization::extended_type_info * true_type =
 
390
                i.get_derived_extended_type_info(t);
 
391
 
 
392
            // note:if this exception is thrown, be sure that derived pointer
 
393
            // is either registered or exported.
 
394
            if(NULL == true_type){
 
395
                boost::serialization::throw_exception(
 
396
                    archive_exception(
 
397
                        archive_exception::unregistered_class,
 
398
                        "derived class not registered or exported"
 
399
                    )
 
400
                );
 
401
            }
 
402
 
 
403
            // if its not a pointer to a more derived type
 
404
            const void *vp = static_cast<const void *>(&t);
 
405
            if(*this_type == *true_type){
 
406
                const basic_pointer_oserializer * bpos = register_type(ar, t);
 
407
                ar.save_pointer(vp, bpos);
 
408
                return;
 
409
            }
 
410
            // convert pointer to more derived type. if this is thrown
 
411
            // it means that the base/derived relationship hasn't be registered
 
412
            vp = serialization::void_downcast(
 
413
                *true_type, 
 
414
                *this_type, 
 
415
                static_cast<const void *>(&t)
 
416
            );
 
417
            if(NULL == vp){
 
418
                boost::serialization::throw_exception(
 
419
                    archive_exception(
 
420
                        archive_exception::unregistered_cast,
 
421
                        true_type->get_debug_info(),
 
422
                        this_type->get_debug_info()
 
423
                    )
 
424
                );
 
425
            }
 
426
 
 
427
            // since true_type is valid, and this only gets made if the 
 
428
            // pointer oserializer object has been created, this should never
 
429
            // fail
 
430
            const basic_pointer_oserializer * bpos
 
431
                = static_cast<const basic_pointer_oserializer *>(
 
432
                    boost::serialization::singleton<
 
433
                        archive_serializer_map<Archive>
 
434
                    >::get_const_instance().find(*true_type)
 
435
                );
 
436
            BOOST_ASSERT(NULL != bpos);
 
437
            if(NULL == bpos)
 
438
                boost::serialization::throw_exception(
 
439
                    archive_exception(
 
440
                        archive_exception::unregistered_class,
 
441
                        "derived class not registered or exported"
 
442
                    )
 
443
                );
 
444
            ar.save_pointer(vp, bpos);
 
445
        }
 
446
    };
 
447
 
 
448
    template<class T>
 
449
    static void save(
 
450
        Archive & ar, 
 
451
        const T & t
 
452
    ){
 
453
        check_pointer_level< T >();
 
454
        check_pointer_tracking< T >();
 
455
        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
 
456
            is_polymorphic< T >,
 
457
            mpl::identity<polymorphic>,
 
458
            mpl::identity<non_polymorphic>
 
459
        >::type type;
 
460
        type::save(ar, const_cast<T &>(t));
 
461
    }
 
462
 
 
463
    template<class TPtr>
 
464
    static void invoke(Archive &ar, const TPtr t){
 
465
        register_type(ar, * t);
 
466
        if(NULL == t){
 
467
            basic_oarchive & boa 
 
468
                = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
 
469
            boa.save_null_pointer();
 
470
            save_access::end_preamble(ar);
 
471
            return;
 
472
        }
 
473
        save(ar, * t);
 
474
    }
 
475
};
 
476
 
 
477
template<class Archive>
 
478
struct save_enum_type
 
479
{
 
480
    template<class T>
 
481
    static void invoke(Archive &ar, const T &t){
 
482
        // convert enum to integers on save
 
483
        const int i = static_cast<int>(t);
 
484
        ar << boost::serialization::make_nvp(NULL, i);
 
485
    }
 
486
};
 
487
 
 
488
template<class Archive>
 
489
struct save_array_type
 
490
{
 
491
    template<class T>
 
492
    static void invoke(Archive &ar, const T &t){
 
493
        typedef BOOST_DEDUCED_TYPENAME boost::remove_extent< T >::type value_type;
 
494
        
 
495
        save_access::end_preamble(ar);
 
496
        // consider alignment
 
497
        std::size_t c = sizeof(t) / (
 
498
            static_cast<const char *>(static_cast<const void *>(&t[1])) 
 
499
            - static_cast<const char *>(static_cast<const void *>(&t[0]))
 
500
        );
 
501
        boost::serialization::collection_size_type count(c);
 
502
        ar << BOOST_SERIALIZATION_NVP(count);
 
503
        ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
 
504
    }
 
505
};
 
506
 
 
507
} // detail
 
508
 
 
509
template<class Archive, class T>
 
510
inline void save(Archive & ar, /*const*/ T &t){
 
511
    typedef 
 
512
        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
 
513
            mpl::identity<detail::save_pointer_type<Archive> >,
 
514
        //else
 
515
        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
 
516
            mpl::identity<detail::save_enum_type<Archive> >,
 
517
        //else
 
518
        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
 
519
            mpl::identity<detail::save_array_type<Archive> >,
 
520
        //else
 
521
            mpl::identity<detail::save_non_pointer_type<Archive> >
 
522
        >
 
523
        >
 
524
        >::type typex;
 
525
    typex::invoke(ar, t);
 
526
}
 
527
 
 
528
} // namespace archive
 
529
} // namespace boost
 
530
 
 
531
#endif // BOOST_ARCHIVE_OSERIALIZER_HPP