-
Notifications
You must be signed in to change notification settings - Fork 3
/
type_info.cc
160 lines (141 loc) · 5.44 KB
/
type_info.cc
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
// $Header$
//
// Copyright (C) 2000 - 2004, by
//
// Carlo Wood, Run on IRC <carlo@alinoe.com>
// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
//
// This file may be distributed under the terms of the Q Public License
// version 1.0 as appearing in the file LICENSE.QPL included in the
// packaging of this file.
//
#include "sys.h"
#include "cwd_debug.h"
#include "libcwd/debug.h"
#include "libcwd/demangle.h"
#include "libcwd/type_info.h"
#include "macros.h"
namespace libcwd {
/**
* \brief Returned by type_info_of() for unknown types.
* \ingroup group_type_info
*/
type_info_ct const unknown_type_info_c(0);
namespace _private_ {
extern void demangle_type(char const* in, _private_::internal_string& out);
// Warning: This LEAKS memory!
// For internal use only
#if __GXX_ABI_VERSION == 0
char const* extract_exact_name(char const* encap_mangled_name LIBCWD_COMMA_TSD_PARAM)
{
size_t len = strlen(encap_mangled_name + 27); // Strip "Q22libcwd_type_info_exact1Z" from the beginning.
set_alloc_checking_off(LIBCWD_TSD);
char* exact_name = new char[len + 1]; // LEAK58
set_alloc_checking_on(LIBCWD_TSD);
strncpy(exact_name, encap_mangled_name + 27, len);
exact_name[len] = 0;
return exact_name;
}
#else
char const* skip_substitution(char const* const ptr, char const* const begin)
{
char const* S_ptr = ptr;
// S_ptr now points to a trailing '_'.
for (int digits = 0; S_ptr > begin && digits < 3; ++digits)
{
--S_ptr;
// All legal substitution patterns have the form "S[0-9A-Z]*_" where we
// limit the number of base-36 digits to two (because it seems extremely
// unlikely that there are more than 1296 substitutions).
//
// We allow "SS_" where the second S is a digit; but not "SSS_" because
// it's already unlikely to have 841 substitutions, too.
if (*S_ptr == 'S' && (digits > 0 || S_ptr[-1] != 'S'))
return S_ptr;
// Substitutions use base-36 with 'digits' [0-9A-Z].
if (!('0' <= *S_ptr && *S_ptr <= '9') && !('A' <= *S_ptr && *S_ptr <= 'Z'))
break;
}
return ptr;
}
// As an example, the input could be:
//
// encap_mangled_name = 22libcwd_type_info_exactIRKN4evio14AcceptedSocketI23MyAcceptedSocketDecoderNS0_12OutputStreamEEEE
// stripped_mangled_name = N4evio14AcceptedSocketI23MyAcceptedSocketDecoderNS _12OutputStreamEEE
// where the space in the latter is not really there (just added for alignment) -------^
char const* extract_exact_name(char const* encap_mangled_name, char const* stripped_mangled_name LIBCWD_COMMA_TSD_PARAM)
{
encap_mangled_name += 25; // Strip "22libcwd_type_info_exactI" from the beginning.
// encap_mangled_name now points to the qualifiers string (if any) "RK".
char const* encap_ptr = encap_mangled_name + strlen(encap_mangled_name) - 1;
// encap_ptr now points to the last E of encap_mangled_name.
size_t len = strlen(stripped_mangled_name);
char const* ptr = stripped_mangled_name + len;
// ptr now points to the terminating zero of stripped_mangled_name.
while (ptr > stripped_mangled_name)
{
--ptr;
--encap_ptr;
LIBCWD_ASSERT(*ptr == *encap_ptr); // This is how we assume the encapsulation works!
if (*ptr == '_')
{
// Now we want to put both pointers on the 'S',
// but only if this could be a substitution.
ptr = skip_substitution(ptr, stripped_mangled_name);
encap_ptr = skip_substitution(encap_ptr, encap_mangled_name);
}
}
// ptr is now equal to stripped_mangled_name, and encap_ptr points to the first character after the qualifiers.
size_t qlen = encap_ptr - encap_mangled_name;
set_alloc_checking_off(LIBCWD_TSD);
char* exact_name = new char[qlen + len + 1]; // LEAK58
set_alloc_checking_on(LIBCWD_TSD);
// Add the qualifiers to the mangled name:
strncpy(exact_name, encap_mangled_name, qlen);
strcpy(exact_name + qlen, stripped_mangled_name);
return exact_name;
}
#endif
// Idem
char const* make_label(char const* mangled_name)
{
char const* label;
LIBCWD_TSD_DECLARATION;
set_alloc_checking_off(LIBCWD_TSD);
{
internal_string out;
demangle_type(mangled_name, out);
label = strcpy(new char[out.size() + 1], out.c_str()); // LEAK44
}
set_alloc_checking_on(LIBCWD_TSD);
return label;
}
type_info_ct type_info<void*>::S_value;
bool type_info<void*>::S_initialized;
type_info_ct const& type_info<void*>::value()
{
if (!S_initialized)
{
S_value.init(typeid(void*).name(), sizeof(void*), 0 /* unknown */);
S_initialized = true;
}
return S_value;
}
} // namespace _private_
} // namespace libcwd
libcwd::type_info_ct libcwd_type_info_exact<void*>::S_value;
bool libcwd_type_info_exact<void*>::S_initialized;
libcwd::type_info_ct const& libcwd_type_info_exact<void*>::value()
{
if (!S_initialized)
{
#if __GXX_ABI_VERSION == 0
S_value.init(::libcwd::_private_::extract_exact_name(typeid(libcwd_type_info_exact<void*>).name() LIBCWD_COMMA_TSD_INSTANCE), sizeof(void*), 0 /* unknown */);
#else
S_value.init(::libcwd::_private_::extract_exact_name(typeid(libcwd_type_info_exact<void*>).name(), typeid(void*).name() LIBCWD_COMMA_TSD_INSTANCE), sizeof(void*), 0 /* unknown */);
#endif
S_initialized = true;
}
return S_value;
}