Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TypeManip.cxx
Go to the documentation of this file.
1// Bindings
2#include "cpyrt.h"
3
4using namespace cppjit;
5#include "TypeManip.h"
6
7// Standard
8#include <algorithm>
9#include <ctype.h>
10#include <sstream>
11
12//- helpers ------------------------------------------------------------------
13static inline bool is_varchar(char c) {
14 return isalnum((int)c) || c == '_' || c == ')' ||
15 c == '(' /* for (anonymous)/(unnamed) */;
16}
17
18static inline std::string::size_type
19find_qualifier_index(const std::string& name) {
20 // Find the first location that is not part of the class name proper.
21 std::string::size_type i = name.size() - 1;
22 bool arr_open = false;
23 for (; 0 < i; --i) {
24 std::string::value_type c = name[i];
25 if (!arr_open && (is_varchar(c) || c == '>')) {
26 if (c == 't' && 6 < i && !is_varchar(name[i - 5]) &&
27 name.substr(i - 4, 5) == "const")
28 i -= 4; // this skips 'const' on a pointer type
29 else
30 break;
31 } else if (c == ']') {
32 arr_open = true;
33 } else if (c == '[') {
34 arr_open = false;
35 }
36 }
37
38 return i + 1;
39}
40
41static inline void erase_const(std::string& name) {
42 // Find and remove all occurrence of 'const'.
43 if (name.empty())
44 return;
45
46 std::string::size_type spos = std::string::npos;
47 std::string::size_type start = 0;
48 while ((spos = name.find("const", start)) != std::string::npos) {
49 // make sure not to erase 'const' as part of the name: if it is
50 // connected, before or after, to a variable name, then keep it
51 std::string::size_type after = spos + 5;
52 if (after < name.size() && is_varchar(name[after])) {
53 start = after;
54 continue;
55 } else if (after == name.size()) {
56 if (spos > 0 && is_varchar(name[spos - 1]))
57 break;
58 }
59
60 std::string::size_type i = 5;
61 while (name[spos + i] == ' ')
62 ++i;
63 name.swap(name.erase(spos, i));
64 }
65}
66
67static inline void rstrip(std::string& name) {
68 // Remove space from the right side of name.
69 std::string::size_type i = name.size();
70 for (; 0 < i; --i) {
71 if (!isspace(name[i - 1]))
72 break;
73 }
74
75 if (i != name.size())
76 name = name.substr(0, i);
77}
78
79//----------------------------------------------------------------------------
80std::string cpyrt::TypeManip::remove_const(const std::string& cppname) {
81 // Remove 'const' qualifiers from the given C++ name.
82 std::string::size_type tmplt_start = cppname.find('<');
83 std::string::size_type type_stop = cppname.rfind('>');
84 if (cppname.find("::", type_stop + 1) !=
85 std::string::npos) // e.g. klass<T>::some_typedef
86 type_stop = cppname.find(' ', type_stop + 1);
87 if (tmplt_start != std::string::npos && cppname[tmplt_start + 1] != '<') {
88 // only replace const qualifying cppname, not in template parameters
89 std::string pre = cppname.substr(0, tmplt_start);
90 erase_const(pre);
91 std::string post = "";
92 if (type_stop != std::string::npos && type_stop != cppname.size() - 1) {
93 post = cppname.substr(type_stop + 1, std::string::npos);
94 erase_const(post);
95 }
96
97 return pre + cppname.substr(tmplt_start, type_stop + 1 - tmplt_start) +
98 post;
99 }
100
101 std::string clean_name = cppname;
102 erase_const(clean_name);
103 return clean_name;
104}
105
106//----------------------------------------------------------------------------
107std::string cpyrt::TypeManip::clean_type(const std::string& cppname,
108 bool template_strip,
109 bool const_strip) {
110 // Strip C++ name from all qualifiers and compounds.
111 std::string::size_type i = find_qualifier_index(cppname);
112 std::string name = cppname.substr(0, i);
113 rstrip(name);
114
115 if (name.back() == ']') { // array type?
116 // TODO: this fails templates instantiated on arrays (not common)
117 name = name.substr(0, name.find('['));
118 } else if (template_strip && name.back() == '>') {
119 name = name.substr(0, name.find('<'));
120 }
121
122 if (const_strip) {
123 if (template_strip)
125 else
127 }
128
129 return name;
130}
131
132//----------------------------------------------------------------------------
133std::string cpyrt::TypeManip::template_base(const std::string& cppname) {
134 // If this is a template, return the underlying template name w/o arguments
135 if (cppname.empty() || cppname.back() != '>')
136 return cppname;
137
138 int tpl_open = 0;
139 for (std::string::size_type pos = cppname.size() - 1; 0 < pos; --pos) {
140 std::string::value_type c = cppname[pos];
141
142 // count '<' and '>' to be able to skip template contents
143 if (c == '>')
144 --tpl_open;
145 else if (c == '<' && cppname[pos + 1] != '<')
146 ++tpl_open;
147
148 if (tpl_open == 0)
149 return cppname.substr(0, pos);
150 }
151
152 return cppname;
153}
154
155//----------------------------------------------------------------------------
156std::string cpyrt::TypeManip::compound(const std::string& name) {
157 // FIXME: temporary fix for translation unit decl being passed in
158 // CreateExecutor from InitExecutor_ (run test10_object_identity), remove
159 // later
160 if (name.empty())
161 return "";
162 // Break down the compound of a fully qualified type name.
163 std::string cleanName = remove_const(name);
164 auto idx = find_qualifier_index(cleanName);
165
166 std::string cpd = cleanName.substr(idx, std::string::npos);
167
168 // for easy identification of fixed size arrays
169 if (!cpd.empty() && cpd.back() == ']') {
170 if (cpd.front() == '[')
171 return "[]"; // fixed array any; dimensions handled separately
172
173 std::ostringstream scpd;
174 scpd << cpd.substr(0, cpd.find('[')) << "[]";
175 cpd = scpd.str();
176 }
177
178 // XXX: remove this hack
179 if (!cpd.empty() && cpd[0] == ' ')
180 return cpd.substr(1, cpd.length() - 1);
181
182 return cpd;
183}
184
185//----------------------------------------------------------------------------
186void cpyrt::TypeManip::cppscope_to_pyscope(std::string& cppscope) {
187 // Change '::' in C++ scope into '.' as in a Python scope.
188 std::string::size_type pos = 0;
189 while ((pos = cppscope.find("::", pos)) != std::string::npos) {
190 cppscope.replace(pos, 2, ".");
191 pos += 1;
192 }
193}
194
195//----------------------------------------------------------------------------
196void cpyrt::TypeManip::cppscope_to_legalname(std::string& cppscope) {
197 // Change characters illegal in a variable name into '_' to form a legal name.
198 for (char& c : cppscope) {
199 for (char needle : {':', '>', '<', ' ', ',', '&', '=', '*', '-'})
200 if (c == needle)
201 c = '_';
202 }
203}
204
205//----------------------------------------------------------------------------
206std::string cpyrt::TypeManip::extract_namespace(const std::string& name) {
207 // Find the namespace the named class lives in, take care of templates
208 if (name.empty())
209 return name;
210
211 int tpl_open = 0;
212 for (std::string::size_type pos = name.size() - 1; 0 < pos; --pos) {
213 std::string::value_type c = name[pos];
214
215 // count '<' and '>' to be able to skip template contents
216 if (c == '>')
217 --tpl_open;
218 else if (c == '<' && name[pos + 1] != '<')
219 ++tpl_open;
220
221 // collect name up to "::"
222 else if (tpl_open == 0 && c == ':' && name[pos - 1] == ':') {
223 // found the extend of the scope ... done
224 return name.substr(0, pos - 1);
225 }
226 }
227
228 // no namespace; assume outer scope
229 return "";
230}
231
232//----------------------------------------------------------------------------
233std::vector<std::string>
234cpyrt::TypeManip::extract_arg_types(const std::string& sig) {
235 // break out the argument types from the signature string
236 std::vector<std::string> result;
237
238 if (sig.empty() || sig == "()")
239 return result;
240
241 int tpl_open = 0;
242 std::string::size_type start = 1;
243 for (std::string::size_type pos = 1; pos < sig.size() - 1; ++pos) {
244 std::string::value_type c = sig[pos];
245
246 // count '<' and '>' to be able to skip template contents
247 if (c == '>')
248 --tpl_open;
249 else if (c == '<' && sig[pos + 1] != '<')
250 ++tpl_open;
251
252 // collect type name up to ',' or end ')'
253 else if (tpl_open == 0 && c == ',') {
254 // found the extend of the scope ... done
255 result.push_back(sig.substr(start, pos - start));
256 start = pos + 1;
257 }
258 }
259
260 // add last type
261 result.push_back(sig.substr(start, sig.rfind(")") - start));
262
263 return result;
264}
265
266//----------------------------------------------------------------------------
267Py_ssize_t cpyrt::TypeManip::array_size(const std::string& name) {
268 // Extract the array size from a given type name (assumes 1D arrays)
269 std::string cleanName = remove_const(name);
270 if (cleanName[cleanName.size() - 1] == ']') {
271 std::string::size_type idx = cleanName.rfind('[');
272 if (idx != std::string::npos) {
273 const std::string asize = cleanName.substr(idx + 1, cleanName.size() - 2);
274 return strtoul(asize.c_str(), nullptr, 0);
275 }
276 }
277
278 return -1;
279}
#define c(i)
Definition RSha256.hxx:101
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char name[80]
Definition TGX11.cxx:142
static void rstrip(std::string &name)
Definition TypeManip.cxx:67
static std::string::size_type find_qualifier_index(const std::string &name)
Definition TypeManip.cxx:19
static void erase_const(std::string &name)
Definition TypeManip.cxx:41
static bool is_varchar(char c)
Definition TypeManip.cxx:13
std::string extract_namespace(const std::string &name)
std::string remove_const(const std::string &cppname)
Definition TypeManip.cxx:80
std::vector< std::string > extract_arg_types(const std::string &sig)
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
Py_ssize_t array_size(const std::string &name)
std::string compound(const std::string &name)
void cppscope_to_pyscope(std::string &cppscope)
void cppscope_to_legalname(std::string &cppscope)
std::string template_base(const std::string &cppname)
Definition API.cxx:34