Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / archive / detail / oserializer.hpp @ 2486

History | View | Annotate | Download (16.9 kB)

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)
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
                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
            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
            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
            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
            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
            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
            typename 
377
            boost::serialization::type_info_implementation< T >::type const
378
            & i = boost::serialization::singleton<
379
                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 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 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
        typename mpl::eval_if<is_pointer< T >,
513
            mpl::identity<detail::save_pointer_type<Archive> >,
514
        //else
515
        typename mpl::eval_if<is_enum< T >,
516
            mpl::identity<detail::save_enum_type<Archive> >,
517
        //else
518
        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