Support const member function pointers & function pointer return values
This commit is contained in:
parent
6e11755d6e
commit
97a0cf2c7f
84
src/lib.rs
84
src/lib.rs
|
@ -34,8 +34,9 @@ fn demange_template_args(mut str: &str) -> Option<(&str, String)> {
|
||||||
let mut qualified = str.to_string();
|
let mut qualified = str.to_string();
|
||||||
qualified += "<";
|
qualified += "<";
|
||||||
while !args.is_empty() {
|
while !args.is_empty() {
|
||||||
let (arg, rest) = demangle_arg(args)?;
|
let (arg, arg_post, rest) = demangle_arg(args)?;
|
||||||
qualified += arg.as_str();
|
qualified += arg.as_str();
|
||||||
|
qualified += arg_post.as_str();
|
||||||
if rest.is_empty() {
|
if rest.is_empty() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,22 +84,23 @@ fn demangle_qualified_class(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn demangle_arg(mut str: &str) -> Option<(String, &str)> {
|
fn demangle_arg(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
let (pre, mut post, rest) = parse_qualifiers(str);
|
let (mut pre, mut post, rest) = parse_qualifiers(str);
|
||||||
result += pre.as_str();
|
result += pre.as_str();
|
||||||
str = rest;
|
str = rest;
|
||||||
if str.starts_with('Q') || str.starts_with(|c: char| c.is_ascii_digit()) {
|
if str.starts_with('Q') || str.starts_with(|c: char| c.is_ascii_digit()) {
|
||||||
let (_, qualified, rest) = demangle_qualified_class(str)?;
|
let (_, qualified, rest) = demangle_qualified_class(str)?;
|
||||||
result += qualified.as_str();
|
result += qualified.as_str();
|
||||||
result += post.as_str();
|
result += post.as_str();
|
||||||
return Some((result, rest));
|
return Some((result, String::new(), rest));
|
||||||
}
|
}
|
||||||
let mut is_member = false;
|
let mut is_member = false;
|
||||||
|
let mut const_member = false;
|
||||||
if str.starts_with('M') {
|
if str.starts_with('M') {
|
||||||
is_member = true;
|
is_member = true;
|
||||||
let (_, member, rest) = demangle_qualified_class(&str[1..])?;
|
let (_, member, rest) = demangle_qualified_class(&str[1..])?;
|
||||||
post = format!("{}::*{}", member, post);
|
pre = format!("{}::*{}", member, pre);
|
||||||
if !rest.starts_with('F') {
|
if !rest.starts_with('F') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -107,19 +109,30 @@ fn demangle_arg(mut str: &str) -> Option<(String, &str)> {
|
||||||
if is_member || str.starts_with('F') {
|
if is_member || str.starts_with('F') {
|
||||||
str = &str[1..];
|
str = &str[1..];
|
||||||
if is_member {
|
if is_member {
|
||||||
// Member functions always(?) include "const void*, void*"
|
// "const void*, const void*" or "const void*, void*"
|
||||||
if !str.starts_with("PCvPv") {
|
if str.starts_with("PCvPCv") {
|
||||||
|
const_member = true;
|
||||||
|
str = &str[6..];
|
||||||
|
} else if str.starts_with("PCvPv") {
|
||||||
|
str = &str[5..];
|
||||||
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
str = &str[5..];
|
} else if post.ends_with('*') {
|
||||||
|
post = post[..post.len() - 1].to_string();
|
||||||
|
pre = format!("*{}", pre);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
let (args, rest) = demangle_function_args(str)?;
|
let (args, rest) = demangle_function_args(str)?;
|
||||||
if !rest.starts_with('_') {
|
if !rest.starts_with('_') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (ret, rest) = demangle_arg(&rest[1..])?;
|
let (ret_pre, ret_post, rest) = demangle_arg(&rest[1..])?;
|
||||||
result += format!("{} ({})({})", ret, post, args).as_str();
|
let const_str = if const_member { " const" } else { "" };
|
||||||
return Some((result, rest));
|
let res_pre = format!("{} ({}{}", ret_pre, pre, post);
|
||||||
|
let res_post = format!(")({}){}{}", args, const_str, ret_post);
|
||||||
|
return Some((res_pre, res_post, rest));
|
||||||
}
|
}
|
||||||
if str.starts_with('A') {
|
if str.starts_with('A') {
|
||||||
todo!("array")
|
todo!("array")
|
||||||
|
@ -139,7 +152,7 @@ fn demangle_arg(mut str: &str) -> Option<(String, &str)> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
});
|
});
|
||||||
result += post.as_str();
|
result += post.as_str();
|
||||||
Some((result, &str[1..]))
|
Some((result, String::new(), &str[1..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn demangle_function_args(mut str: &str) -> Option<(String, &str)> {
|
fn demangle_function_args(mut str: &str) -> Option<(String, &str)> {
|
||||||
|
@ -148,8 +161,9 @@ fn demangle_function_args(mut str: &str) -> Option<(String, &str)> {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
let (arg, rest) = demangle_arg(str)?;
|
let (arg, arg_post, rest) = demangle_arg(str)?;
|
||||||
result += arg.as_str();
|
result += arg.as_str();
|
||||||
|
result += arg_post.as_str();
|
||||||
str = rest;
|
str = rest;
|
||||||
if str.starts_with('_') || str.starts_with(',') {
|
if str.starts_with('_') || str.starts_with(',') {
|
||||||
break;
|
break;
|
||||||
|
@ -215,6 +229,9 @@ pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
let mut special = false;
|
let mut special = false;
|
||||||
let mut cnst = false;
|
let mut cnst = false;
|
||||||
let mut fn_name: String;
|
let mut fn_name: String;
|
||||||
|
let mut return_type_pre = String::new();
|
||||||
|
let mut return_type_post = String::new();
|
||||||
|
let mut qualified = String::new();
|
||||||
if str.starts_with("__") {
|
if str.starts_with("__") {
|
||||||
special = true;
|
special = true;
|
||||||
str = &str[2..];
|
str = &str[2..];
|
||||||
|
@ -226,11 +243,14 @@ pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
fn_name = qualified;
|
fn_name = qualified;
|
||||||
str = &rest[2..];
|
str = &rest[2..];
|
||||||
}
|
}
|
||||||
let (class_name, mut qualified, rest) = demangle_qualified_class(str)?;
|
if !str.starts_with('F') {
|
||||||
|
let (class_name, qualified_class, rest) = demangle_qualified_class(str)?;
|
||||||
|
qualified = qualified_class;
|
||||||
str = rest;
|
str = rest;
|
||||||
if special {
|
if special {
|
||||||
fn_name = demangle_special_function(fn_name.as_str(), class_name.as_str())?;
|
fn_name = demangle_special_function(fn_name.as_str(), class_name.as_str())?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if str.starts_with('C') {
|
if str.starts_with('C') {
|
||||||
str = &str[1..];
|
str = &str[1..];
|
||||||
cnst = true;
|
cnst = true;
|
||||||
|
@ -243,8 +263,9 @@ pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
}
|
}
|
||||||
if str.starts_with('_') {
|
if str.starts_with('_') {
|
||||||
str = &str[1..];
|
str = &str[1..];
|
||||||
let (ret, rest) = demangle_arg(str)?;
|
let (ret_pre, ret_post, rest) = demangle_arg(str)?;
|
||||||
qualified = format!("{} {}", ret, qualified);
|
return_type_pre = ret_pre;
|
||||||
|
return_type_post = ret_post;
|
||||||
str = rest;
|
str = rest;
|
||||||
}
|
}
|
||||||
if !str.is_empty() {
|
if !str.is_empty() {
|
||||||
|
@ -254,7 +275,10 @@ pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
fn_name = format!("{} const", fn_name);
|
fn_name = format!("{} const", fn_name);
|
||||||
}
|
}
|
||||||
if !qualified.is_empty() {
|
if !qualified.is_empty() {
|
||||||
return Some(format!("{}::{}", qualified, fn_name));
|
fn_name = format!("{}::{}", qualified, fn_name);
|
||||||
|
}
|
||||||
|
if !return_type_pre.is_empty() {
|
||||||
|
fn_name = format!("{} {}{}", return_type_pre, fn_name, return_type_post);
|
||||||
}
|
}
|
||||||
Some(fn_name)
|
Some(fn_name)
|
||||||
}
|
}
|
||||||
|
@ -300,19 +324,19 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_demangle_arg() {
|
fn test_demangle_arg() {
|
||||||
assert_eq!(demangle_arg("v"), Some(("void".to_string(), "")));
|
assert_eq!(demangle_arg("v"), Some(("void".to_string(), "".to_string(), "")));
|
||||||
assert_eq!(demangle_arg("b"), Some(("bool".to_string(), "")));
|
assert_eq!(demangle_arg("b"), Some(("bool".to_string(), "".to_string(), "")));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_arg("RC9CVector3fUc"),
|
demangle_arg("RC9CVector3fUc"),
|
||||||
Some(("const CVector3f&".to_string(), "Uc"))
|
Some(("const CVector3f&".to_string(), "".to_string(), "Uc"))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_arg("Q24rstl14char_traits<w>,"),
|
demangle_arg("Q24rstl14char_traits<w>,"),
|
||||||
Some(("rstl::char_traits<wchar_t>".to_string(), ","))
|
Some(("rstl::char_traits<wchar_t>".to_string(), "".to_string(), ","))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_arg("PFPCcPCc_v"),
|
demangle_arg("PFPCcPCc_v"),
|
||||||
Some(("void (*)(const char*, const char*)".to_string(), ""))
|
Some(("void (*".to_string(), ")(const char*, const char*)".to_string(), ""))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,5 +389,21 @@ mod tests {
|
||||||
demangle("AddWidgetFnMap__10CGuiWidgetFiM10CGuiWidgetFPCvPvP15CGuiFunctionDefP18CGuiControllerInfo_i"),
|
demangle("AddWidgetFnMap__10CGuiWidgetFiM10CGuiWidgetFPCvPvP15CGuiFunctionDefP18CGuiControllerInfo_i"),
|
||||||
Some("CGuiWidget::AddWidgetFnMap(int, int (CGuiWidget::*)(CGuiFunctionDef*, CGuiControllerInfo*))".to_string())
|
Some("CGuiWidget::AddWidgetFnMap(int, int (CGuiWidget::*)(CGuiFunctionDef*, CGuiControllerInfo*))".to_string())
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle("BareFn__FPFPCcPv_v_v"),
|
||||||
|
Some("void BareFn(void (*)(const char*, void*))".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle("BareFn__FPFPCcPv_v_PFPCvPv_v"),
|
||||||
|
Some("void (* BareFn(void (*)(const char*, void*)))(const void*, void*)".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle("SomeFn__FRCPFPFPCvPv_v_RCPFPCvPv_v"),
|
||||||
|
Some("SomeFn(void (*const & (*const &)(void (*)(const void*, void*)))(const void*, void*))".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle("SomeFn__Q29Namespace5ClassCFRCMQ29Namespace5ClassFPCvPCvMQ29Namespace5ClassFPCvPCvPCvPv_v_RCMQ29Namespace5ClassFPCvPCvPCvPv_v"),
|
||||||
|
Some("Namespace::Class::SomeFn(void (Namespace::Class::*const & (Namespace::Class::*const &)(void (Namespace::Class::*)(const void*, void*) const) const)(const void*, void*) const) const".to_string())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue