~ubuntu-branches/ubuntu/wily/bombono-dvd/wily

« back to all changes in this revision

Viewing changes to src/mlib/adobe/typeinfo.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2010-11-04 11:46:25 UTC
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20101104114625-8xfdhvhpsm51i0nu
Tags: upstream-0.8.0
ImportĀ upstreamĀ versionĀ 0.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright 2005-2007 Adobe Systems Incorporated
 
3
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
 
4
    or a copy at http://stlab.adobe.com/licenses.html)
 
5
*/
 
6
 
 
7
/**************************************************************************************************/
 
8
 
 
9
#include <mlib/adobe/typeinfo.hpp>
 
10
 
 
11
#include <fstream>
 
12
#include <iterator>
 
13
#include <map>
 
14
#include <sstream>
 
15
 
 
16
//#include <adobe/string.hpp>
 
17
//#include <adobe/cstring.hpp>
 
18
 
 
19
/**************************************************************************************************/
 
20
 
 
21
namespace adobe {
 
22
 
 
23
/**************************************************************************************************/
 
24
 
 
25
bad_cast::bad_cast() : what_m("bad_cast") { }
 
26
 
 
27
bad_cast::bad_cast(const bad_cast& error) : my_parent(), what_m(error.what_m) { }
 
28
 
 
29
/*
 
30
REVISIT (sparent) : This is only for debugging, but a reliable way to map a type to a name would
 
31
be a useful addition.
 
32
*/
 
33
 
 
34
bad_cast::bad_cast(const std::type_info& from, const std::type_info& to) :
 
35
    what_m("bad_cast: ")
 
36
{
 
37
    what_m += std::string(from.name()) + " -> " + to.name();
 
38
}
 
39
 
 
40
bad_cast::bad_cast(const type_info_t& from, const type_info_t& to) :
 
41
    what_m("bad_cast: ")
 
42
{
 
43
    std::back_insert_iterator<std::string> out(what_m);
 
44
    out = serialize(from, out);
 
45
    out = copy(boost::as_literal(" -> "), out);
 
46
    out = serialize(to, out);
 
47
}
 
48
 
 
49
bad_cast& bad_cast::operator=(const bad_cast& error)
 
50
{ what_m = error.what_m; return *this; }
 
51
 
 
52
bad_cast::~bad_cast() throw()
 
53
{ }
 
54
 
 
55
const char* bad_cast::what() const throw()
 
56
{ return what_m.c_str(); }
 
57
 
 
58
/**************************************************************************************************/
 
59
 
 
60
#ifndef NDEBUG
 
61
 
 
62
namespace version_1 {
 
63
 
 
64
std::ostream& operator<<(std::ostream& stream, const type_info_t& x)
 
65
{
 
66
    std::ostream_iterator<char> out(stream);
 
67
    serialize(x, out);
 
68
    return stream;
 
69
}
 
70
 
 
71
} // namespace version_1
 
72
 
 
73
#endif
 
74
 
 
75
/**************************************************************************************************/
 
76
 
 
77
namespace implementation {
 
78
 
 
79
 
 
80
/**************************************************************************************************/
 
81
 
 
82
const char* cppfilt(const std::type_info& type)
 
83
{
 
84
#if defined(__GNUC__)
 
85
    /*
 
86
        WARNING (fbrereto) : This code is not thread safe! iostreams in general
 
87
                             are not, so it is the responsibility of the client
 
88
                             to assert thread safety for any serialization.
 
89
 
 
90
        This bit of code attempts to use std::system to make a call out to
 
91
        c++filt in an attempt to demangle the c++ type name found in the
 
92
        type_info struct. This code is only active for gcc, as 1) c++filt is
 
93
        only part of the GNU development tools, and 2) MSVC already
 
94
        pretty-prints its type_info name. There are many things that can go
 
95
        wrong with this code, so I've tried to be as conservative as possible in
 
96
        making the call out to c++filt. Given any error state the (mangled) name
 
97
        found in the std::type_info struct will be used.
 
98
 
 
99
        All calls to std::system are synchronous.
 
100
    */
 
101
    static const bool system_available_s(std::system(0) != 0);
 
102
    static const bool cpp_filt_available_s(system_available_s && std::system("c++filt foo > /dev/null") == 0);
 
103
 
 
104
    if (!cpp_filt_available_s)
 
105
        return type.name();
 
106
 
 
107
    typedef std::map<const std::type_info*, std::string> demangle_map_t;
 
108
 
 
109
    // We cache the demangled types as we look them up; solves the const char*
 
110
    // ownership problem and speeds things up the next time around.
 
111
    static demangle_map_t demangle_map_s;
 
112
 
 
113
    demangle_map_t::const_iterator found(demangle_map_s.find(&type));
 
114
 
 
115
    if (found != demangle_map_s.end()) // cache hit
 
116
        return found->second.c_str();
 
117
 
 
118
    // This is a bit hacky... std::system returns the error code from the shell,
 
119
    // and that's it, so any information produced by c++filt is piped to a temp
 
120
    // file and sucked back in using an input file stream.
 
121
 
 
122
    static const char* filepath("/tmp/cppfilt_demangle.txt");
 
123
    std::stringstream  stream;
 
124
 
 
125
    stream << "c++filt -_ -t '" << type.name() << "' > " << filepath;
 
126
 
 
127
    if (std::system(stream.str().c_str()) != 0)
 
128
        return type.name();
 
129
 
 
130
    std::ifstream input(filepath);
 
131
 
 
132
    if (input.is_open() == false)
 
133
        return type.name();
 
134
 
 
135
    std::string result;
 
136
 
 
137
    getline(input, result);
 
138
 
 
139
    demangle_map_s[&type].assign(result);
 
140
 
 
141
    return demangle_map_s[&type].c_str();
 
142
#else
 
143
    return type.name();
 
144
#endif
 
145
}
 
146
 
 
147
/**************************************************************************************************/
 
148
 
 
149
bool type_instance_t::requires_std_rtti() const
 
150
{
 
151
    if (type_info_m) return true;
 
152
    
 
153
    for (const type_instance_t* const* xp = &parameter_m[0]; *xp; ++xp) {
 
154
        if ((*xp)->requires_std_rtti()) return true;
 
155
    }
 
156
    
 
157
    return false;
 
158
}
 
159
 
 
160
bool operator==(const type_instance_t& x, const type_instance_t& y)
 
161
{
 
162
    /*
 
163
        NOTE (sparent@adobe.com) : Because we frequently check type info's when we know they should
 
164
        be equal and the identity will be equal unless they have been passed through a DLL boundary,
 
165
        this is a valid optimization.
 
166
    */
 
167
    
 
168
    if (&x == &y) return true;
 
169
 
 
170
    if (x.type_info_m) {
 
171
        if (y.type_info_m) return *x.type_info_m == *y.type_info_m;
 
172
        return false;
 
173
    }
 
174
    if (y.type_info_m) return false;
 
175
    
 
176
    if (strcmp(x.name_m, y.name_m) != 0) return false;
 
177
 
 
178
    const type_instance_t* const* xp = &x.parameter_m[0];
 
179
    const type_instance_t* const* yp = &y.parameter_m[0];
 
180
    
 
181
    while (*xp && *yp) {
 
182
        if (**xp != **yp) return false;
 
183
        ++xp;
 
184
        ++yp;
 
185
    }
 
186
    return *xp == *yp; // at least one is zero - both zero implies equality.
 
187
}
 
188
 
 
189
bool before(const type_instance_t& x, const type_instance_t& y)
 
190
{
 
191
    if (x.type_info_m) {
 
192
        if (y.type_info_m) return x.type_info_m->before(*y.type_info_m) != 0;
 
193
        return false; // All local types sort after named types
 
194
    }
 
195
    if (y.type_info_m) return true;
 
196
    
 
197
    int c = strcmp(x.name_m, y.name_m);
 
198
    if (c != 0) return c < 0 ? true : false;
 
199
    
 
200
    const type_instance_t* const* xp = &x.parameter_m[0];
 
201
    const type_instance_t* const* yp = &y.parameter_m[0];
 
202
    
 
203
    /*
 
204
        REVISIT (sparent) : The two compares in this loop are necessary for a lexicographical
 
205
        compare. An alternative would be a single three - way compare. That might end up being
 
206
        less work overall. If too much time is spent in this code then it should be considered.
 
207
    */
 
208
    
 
209
    while (*xp && *yp) {
 
210
        if (before(**xp, **yp)) return true;
 
211
        if (before(**yp, **xp)) return false;
 
212
        ++xp;
 
213
        ++yp;
 
214
    }
 
215
    return *yp != 0;
 
216
}
 
217
 
 
218
/**************************************************************************************************/
 
219
 
 
220
} // namespace implementation
 
221
 
 
222
/**************************************************************************************************/
 
223
 
 
224
} // namespace adobe
 
225
 
 
226
/**************************************************************************************************/