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)
7
/**************************************************************************************************/
9
#include <mlib/adobe/typeinfo.hpp>
16
//#include <adobe/string.hpp>
17
//#include <adobe/cstring.hpp>
19
/**************************************************************************************************/
23
/**************************************************************************************************/
25
bad_cast::bad_cast() : what_m("bad_cast") { }
27
bad_cast::bad_cast(const bad_cast& error) : my_parent(), what_m(error.what_m) { }
30
REVISIT (sparent) : This is only for debugging, but a reliable way to map a type to a name would
34
bad_cast::bad_cast(const std::type_info& from, const std::type_info& to) :
37
what_m += std::string(from.name()) + " -> " + to.name();
40
bad_cast::bad_cast(const type_info_t& from, const type_info_t& to) :
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);
49
bad_cast& bad_cast::operator=(const bad_cast& error)
50
{ what_m = error.what_m; return *this; }
52
bad_cast::~bad_cast() throw()
55
const char* bad_cast::what() const throw()
56
{ return what_m.c_str(); }
58
/**************************************************************************************************/
64
std::ostream& operator<<(std::ostream& stream, const type_info_t& x)
66
std::ostream_iterator<char> out(stream);
71
} // namespace version_1
75
/**************************************************************************************************/
77
namespace implementation {
80
/**************************************************************************************************/
82
const char* cppfilt(const std::type_info& type)
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.
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.
99
All calls to std::system are synchronous.
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);
104
if (!cpp_filt_available_s)
107
typedef std::map<const std::type_info*, std::string> demangle_map_t;
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;
113
demangle_map_t::const_iterator found(demangle_map_s.find(&type));
115
if (found != demangle_map_s.end()) // cache hit
116
return found->second.c_str();
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.
122
static const char* filepath("/tmp/cppfilt_demangle.txt");
123
std::stringstream stream;
125
stream << "c++filt -_ -t '" << type.name() << "' > " << filepath;
127
if (std::system(stream.str().c_str()) != 0)
130
std::ifstream input(filepath);
132
if (input.is_open() == false)
137
getline(input, result);
139
demangle_map_s[&type].assign(result);
141
return demangle_map_s[&type].c_str();
147
/**************************************************************************************************/
149
bool type_instance_t::requires_std_rtti() const
151
if (type_info_m) return true;
153
for (const type_instance_t* const* xp = ¶meter_m[0]; *xp; ++xp) {
154
if ((*xp)->requires_std_rtti()) return true;
160
bool operator==(const type_instance_t& x, const type_instance_t& y)
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.
168
if (&x == &y) return true;
171
if (y.type_info_m) return *x.type_info_m == *y.type_info_m;
174
if (y.type_info_m) return false;
176
if (strcmp(x.name_m, y.name_m) != 0) return false;
178
const type_instance_t* const* xp = &x.parameter_m[0];
179
const type_instance_t* const* yp = &y.parameter_m[0];
182
if (**xp != **yp) return false;
186
return *xp == *yp; // at least one is zero - both zero implies equality.
189
bool before(const type_instance_t& x, const type_instance_t& y)
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
195
if (y.type_info_m) return true;
197
int c = strcmp(x.name_m, y.name_m);
198
if (c != 0) return c < 0 ? true : false;
200
const type_instance_t* const* xp = &x.parameter_m[0];
201
const type_instance_t* const* yp = &y.parameter_m[0];
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.
210
if (before(**xp, **yp)) return true;
211
if (before(**yp, **xp)) return false;
218
/**************************************************************************************************/
220
} // namespace implementation
222
/**************************************************************************************************/
226
/**************************************************************************************************/