summaryrefslogtreecommitdiffstats
blob: 2efbefc8ff257b618afa7738a99e7a787f7ab974 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// extended_type_info.cpp: implementation for portable version of type_info

// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org for updates, documentation, and revision history.

#if (defined _MSC_VER) && (_MSC_VER == 1200)
#  pragma warning (disable : 4786) // too long name, harmless warning
#endif

#include <algorithm>
#include <set>
#include <utility>
#include <boost/assert.hpp>
#include <cstddef> // NULL

#include <boost/config.hpp> // msvc needs this to suppress warning

#include <cstring>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{ using ::strcmp; }
#endif

#include <boost/detail/no_exceptions_support.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/serialization/force_include.hpp>

#define BOOST_SERIALIZATION_SOURCE
#include <boost/serialization/extended_type_info.hpp>

#ifdef BOOST_MSVC
#  pragma warning(push)
#  pragma warning(disable : 4511 4512)
#endif

namespace boost { 
namespace serialization {
namespace detail {

struct key_compare
{
    bool
    operator()(
        const extended_type_info * lhs, 
        const extended_type_info * rhs
    ) const {
        // performance shortcut
        if(lhs == rhs)
            return false;
        const char * l = lhs->get_key();
        BOOST_ASSERT(NULL != l);
        const char * r = rhs->get_key();
        BOOST_ASSERT(NULL != r);
        // performance shortcut
        // shortcut to exploit string pooling
        if(l == r)
            return false;
        // for exported types, use the string key so that
        // multiple instances in different translation units
        // can be matched up
        return std::strcmp(l, r) < 0;
    }
};

typedef std::multiset<const extended_type_info *, key_compare> ktmap;

#ifdef BOOST_MSVC
#  pragma warning(push)
#  pragma warning(disable : 4511 4512)
#endif

class extended_type_info_arg : public extended_type_info
{
    virtual bool
    is_less_than(const extended_type_info & /*rhs*/) const {
        BOOST_ASSERT(false);
        return false;
    };
    virtual bool
    is_equal(const extended_type_info & /*rhs*/) const {
        BOOST_ASSERT(false);
        return false;
    };
    virtual const char * get_debug_info() const {
        return get_key();
    }
    virtual void * construct(unsigned int /*count*/, ...) const{
        BOOST_ASSERT(false);
        return NULL;
    }
    virtual void destroy(void const * const /*p*/) const {
        BOOST_ASSERT(false);
    }
public:
    extended_type_info_arg(const char * key) :
        extended_type_info(0, key)
    {}

    ~extended_type_info_arg(){
    }
};

#ifdef BOOST_MSVC
#  pragma warning(pop)
#endif

} // namespace detail

BOOST_SERIALIZATION_DECL(void)  
extended_type_info::key_register() const{
    if(NULL == get_key())
        return;
    singleton<detail::ktmap>::get_mutable_instance().insert(this);
}

BOOST_SERIALIZATION_DECL(void)  
extended_type_info::key_unregister() const{
    if(NULL == get_key())
        return;
    if(! singleton<detail::ktmap>::is_destroyed()){
        detail::ktmap & x = singleton<detail::ktmap>::get_mutable_instance();
        detail::ktmap::iterator start = x.lower_bound(this);
        detail::ktmap::iterator end = x.upper_bound(this);
        // remove entry in map which corresponds to this type
        for(;start != end; ++start){
            if(this == *start){
                x.erase(start);
                break;
            }
        }
    }
}

BOOST_SERIALIZATION_DECL(const extended_type_info *) 
extended_type_info::find(const char *key) {
    BOOST_ASSERT(NULL != key);
    const detail::ktmap & k = singleton<detail::ktmap>::get_const_instance();
    const detail::extended_type_info_arg eti_key(key);
    const detail::ktmap::const_iterator it = k.find(& eti_key);
    if(k.end() == it)
        return NULL;
    return *(it);
}

BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
extended_type_info::extended_type_info(
    const unsigned int type_info_key,
    const char * key
) :
    m_type_info_key(type_info_key),
    m_key(key)
{
}

BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) 
extended_type_info::~extended_type_info(){
}

BOOST_SERIALIZATION_DECL(bool)  
extended_type_info::operator<(const extended_type_info &rhs) const {
    // short cut for a common cases
    if(this == & rhs)
        return false;
    if(m_type_info_key == rhs.m_type_info_key){
        return is_less_than(rhs);
    }
    if(m_type_info_key < rhs.m_type_info_key)
        return true;
    return false;
}

BOOST_SERIALIZATION_DECL(bool)
extended_type_info::operator==(const extended_type_info &rhs) const {
    // short cut for a common cases
    if(this == & rhs)
        return true;
    if(m_type_info_key != rhs.m_type_info_key){
        return false;
    }
    return is_equal(rhs);
}

} // namespace serialization
} // namespace boost