Support template args for built-in operators
This commit is contained in:
parent
5318f6ac53
commit
64265e9efb
123
src/lib.rs
123
src/lib.rs
|
@ -26,51 +26,50 @@ fn parse_digits(str: &str) -> Option<(usize, &str)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn demange_template_args(mut str: &str) -> Option<(&str, String)> {
|
fn demangle_template_args(mut str: &str) -> Option<(&str, String)> {
|
||||||
let qualified = if let Some(start_idx) = str.find('<') {
|
let tmpl_args = if let Some(start_idx) = str.find('<') {
|
||||||
let end_idx = str.rfind('>')?;
|
let end_idx = str.rfind('>')?;
|
||||||
let mut args = &str[start_idx + 1..end_idx];
|
let mut args = &str[start_idx + 1..end_idx];
|
||||||
str = &str[..start_idx];
|
str = &str[..start_idx];
|
||||||
let mut qualified = str.to_string();
|
let mut tmpl_args = "<".to_string();
|
||||||
qualified += "<";
|
|
||||||
while !args.is_empty() {
|
while !args.is_empty() {
|
||||||
let (arg, arg_post, rest) = demangle_arg(args)?;
|
let (arg, arg_post, rest) = demangle_arg(args)?;
|
||||||
qualified += arg.as_str();
|
tmpl_args += arg.as_str();
|
||||||
qualified += arg_post.as_str();
|
tmpl_args += arg_post.as_str();
|
||||||
if rest.is_empty() {
|
if rest.is_empty() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
qualified += ", ";
|
tmpl_args += ", ";
|
||||||
}
|
}
|
||||||
args = &rest[1..];
|
args = &rest[1..];
|
||||||
}
|
}
|
||||||
qualified += ">";
|
tmpl_args += ">";
|
||||||
qualified
|
tmpl_args
|
||||||
} else {
|
} else {
|
||||||
str.to_string()
|
String::new()
|
||||||
};
|
};
|
||||||
Some((str, qualified))
|
Some((str, tmpl_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn demangle_class(str: &str) -> Option<(String, String, &str)> {
|
fn demangle_name(str: &str) -> Option<(String, String, &str)> {
|
||||||
let (size, rest) = parse_digits(str)?;
|
let (size, rest) = parse_digits(str)?;
|
||||||
// hack for template argument constants
|
// hack for template argument constants
|
||||||
if rest.is_empty() || rest.starts_with(',') {
|
if rest.is_empty() || rest.starts_with(',') {
|
||||||
let out = format!("{}", size);
|
let out = format!("{}", size);
|
||||||
return Some((out.clone(), out, rest));
|
return Some((out.clone(), out, rest));
|
||||||
}
|
}
|
||||||
let (class_name, qualified) = demange_template_args(&rest[..size])?;
|
let (name, args) = demangle_template_args(&rest[..size])?;
|
||||||
Some((class_name.to_string(), qualified, &rest[size..]))
|
Some((name.to_string(), format!("{}{}", name, args), &rest[size..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn demangle_qualified_class(mut str: &str) -> Option<(String, String, &str)> {
|
fn demangle_qualified_name(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
if str.starts_with('Q') {
|
if str.starts_with('Q') {
|
||||||
let count = usize::from_str(&str[1..2]).ok()?;
|
let count = usize::from_str(&str[1..2]).ok()?;
|
||||||
str = &str[2..];
|
str = &str[2..];
|
||||||
let mut last_class = String::new();
|
let mut last_class = String::new();
|
||||||
let mut qualified = String::new();
|
let mut qualified = String::new();
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let (class_name, full, rest) = demangle_class(str)?;
|
let (class_name, full, rest) = demangle_name(str)?;
|
||||||
qualified += full.as_str();
|
qualified += full.as_str();
|
||||||
last_class = class_name;
|
last_class = class_name;
|
||||||
str = rest;
|
str = rest;
|
||||||
|
@ -80,7 +79,7 @@ fn demangle_qualified_class(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
}
|
}
|
||||||
Some((last_class, qualified, str))
|
Some((last_class, qualified, str))
|
||||||
} else {
|
} else {
|
||||||
demangle_class(str)
|
demangle_name(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ fn demangle_arg(mut str: &str) -> Option<(String, String, &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_name(str)?;
|
||||||
result += qualified.as_str();
|
result += qualified.as_str();
|
||||||
result += post.as_str();
|
result += post.as_str();
|
||||||
return Some((result, String::new(), rest));
|
return Some((result, String::new(), rest));
|
||||||
|
@ -99,7 +98,7 @@ fn demangle_arg(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
let mut const_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_name(&str[1..])?;
|
||||||
pre = format!("{}::*{}", member, pre);
|
pre = format!("{}::*{}", member, pre);
|
||||||
if !rest.starts_with('F') {
|
if !rest.starts_with('F') {
|
||||||
return None;
|
return None;
|
||||||
|
@ -140,7 +139,9 @@ fn demangle_arg(mut str: &str) -> Option<(String, String, &str)> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (arg_pre, arg_post, rest) = demangle_arg(&rest[1..])?;
|
let (arg_pre, arg_post, rest) = demangle_arg(&rest[1..])?;
|
||||||
if !post.is_empty() { post = format!("({})", post); }
|
if !post.is_empty() {
|
||||||
|
post = format!("({})", post);
|
||||||
|
}
|
||||||
result = format!("{}{}{}", pre, arg_pre, post);
|
result = format!("{}{}{}", pre, arg_pre, post);
|
||||||
let ret_post = format!("[{}]{}", count, arg_post);
|
let ret_post = format!("[{}]{}", count, arg_post);
|
||||||
return Some((result, ret_post, rest));
|
return Some((result, ret_post, rest));
|
||||||
|
@ -185,8 +186,10 @@ fn demangle_special_function(str: &str, class_name: &str) -> Option<String> {
|
||||||
let (arg_pre, arg_post, _) = demangle_arg(rest)?;
|
let (arg_pre, arg_post, _) = demangle_arg(rest)?;
|
||||||
return Some(format!("operator {}{}", arg_pre, arg_post));
|
return Some(format!("operator {}{}", arg_pre, arg_post));
|
||||||
}
|
}
|
||||||
Some(
|
let (op, args) = demangle_template_args(str)?;
|
||||||
match str {
|
Some(format!(
|
||||||
|
"{}{}",
|
||||||
|
match op {
|
||||||
"dt" => return Some(format!("~{}", class_name)),
|
"dt" => return Some(format!("~{}", class_name)),
|
||||||
"ct" => class_name,
|
"ct" => class_name,
|
||||||
"nw" => "operator new",
|
"nw" => "operator new",
|
||||||
|
@ -232,9 +235,9 @@ fn demangle_special_function(str: &str, class_name: &str) -> Option<String> {
|
||||||
"cl" => "operator()",
|
"cl" => "operator()",
|
||||||
"vc" => "operator[]",
|
"vc" => "operator[]",
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
},
|
||||||
.to_string(),
|
args
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn demangle(mut str: &str) -> Option<String> {
|
pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
|
@ -254,16 +257,16 @@ pub fn demangle(mut str: &str) -> Option<String> {
|
||||||
if special {
|
if special {
|
||||||
fn_name = fn_name_out.to_string();
|
fn_name = fn_name_out.to_string();
|
||||||
} else {
|
} else {
|
||||||
let (_, qualified) = demange_template_args(fn_name_out)?;
|
let (name, args) = demangle_template_args(fn_name_out)?;
|
||||||
fn_name = qualified;
|
fn_name = format!("{}{}", name, args);
|
||||||
}
|
}
|
||||||
str = &rest[2..];
|
str = &rest[2..];
|
||||||
}
|
}
|
||||||
let mut class_name = String::new();
|
let mut class_name = String::new();
|
||||||
if !str.starts_with('F') {
|
if !str.starts_with('F') {
|
||||||
let (cls, qualified_class, rest) = demangle_qualified_class(str)?;
|
let (name, qualified_name, rest) = demangle_qualified_name(str)?;
|
||||||
class_name = cls;
|
class_name = name;
|
||||||
qualified = qualified_class;
|
qualified = qualified_name;
|
||||||
str = rest;
|
str = rest;
|
||||||
}
|
}
|
||||||
if special {
|
if special {
|
||||||
|
@ -306,29 +309,51 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_demangle_class() {
|
fn test_demangle_template_args() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_class("24single_ptr<10CModelData>"),
|
demangle_template_args("single_ptr<10CModelData>"),
|
||||||
|
Some(("single_ptr", "<CModelData>".to_string()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle_template_args(
|
||||||
|
"basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>"
|
||||||
|
),
|
||||||
Some((
|
Some((
|
||||||
"single_ptr".to_string(),
|
"basic_string",
|
||||||
"single_ptr<CModelData>".to_string(),
|
"<wchar_t, rstl::char_traits<wchar_t>, rstl::rmemory_allocator>".to_string()
|
||||||
""
|
|
||||||
))
|
))
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_demangle_qualified_class() {
|
fn test_demangle_name() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_qualified_class("6CActor"),
|
demangle_name("24single_ptr<10CModelData>"),
|
||||||
|
Some(("single_ptr".to_string(), "single_ptr<CModelData>".to_string(), ""))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle_name("66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>"),
|
||||||
|
Some((
|
||||||
|
"basic_string".to_string(),
|
||||||
|
"basic_string<wchar_t, rstl::char_traits<wchar_t>, rstl::rmemory_allocator>"
|
||||||
|
.to_string(),
|
||||||
|
""
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_demangle_qualified_name() {
|
||||||
|
assert_eq!(
|
||||||
|
demangle_qualified_name("6CActor"),
|
||||||
Some(("CActor".to_string(), "CActor".to_string(), ""))
|
Some(("CActor".to_string(), "CActor".to_string(), ""))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_qualified_class("Q29CVector3f4EDim"),
|
demangle_qualified_name("Q29CVector3f4EDim"),
|
||||||
Some(("EDim".to_string(), "CVector3f::EDim".to_string(), ""))
|
Some(("EDim".to_string(), "CVector3f::EDim".to_string(), ""))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle_qualified_class(
|
demangle_qualified_name(
|
||||||
"Q24rstl66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>"
|
"Q24rstl66basic_string<w,Q24rstl14char_traits<w>,Q24rstl17rmemory_allocator>"
|
||||||
),
|
),
|
||||||
Some((
|
Some((
|
||||||
|
@ -371,10 +396,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_demangle() {
|
fn test_demangle() {
|
||||||
assert_eq!(demangle("cfunction"), None);
|
assert_eq!(demangle("cfunction"), None);
|
||||||
assert_eq!(
|
assert_eq!(demangle("__dt__6CActorFv"), Some("CActor::~CActor(void)".to_string()));
|
||||||
demangle("__dt__6CActorFv"),
|
|
||||||
Some("CActor::~CActor(void)".to_string())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle("GetSfxHandle__6CActorCFv"),
|
demangle("GetSfxHandle__6CActorCFv"),
|
||||||
Some("CActor::GetSfxHandle(void) const".to_string())
|
Some("CActor::GetSfxHandle(void) const".to_string())
|
||||||
|
@ -433,7 +455,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle("__opb__33TFunctor2<CP15CGuiSliderGroup,Cf>CFv"),
|
demangle("__opb__33TFunctor2<CP15CGuiSliderGroup,Cf>CFv"),
|
||||||
Some("TFunctor2<const CGuiSliderGroup*, const float>::operator bool(void) const".to_string())
|
Some(
|
||||||
|
"TFunctor2<const CGuiSliderGroup*, const float>::operator bool(void) const"
|
||||||
|
.to_string()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle("__opRC25TToken<15CCharLayoutInfo>__31TLockedToken<15CCharLayoutInfo>CFv"),
|
demangle("__opRC25TToken<15CCharLayoutInfo>__31TLockedToken<15CCharLayoutInfo>CFv"),
|
||||||
|
@ -453,7 +478,9 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle("CalculateFluidTextureOffset__14CFluidUVMotionCFfPA2_f"),
|
demangle("CalculateFluidTextureOffset__14CFluidUVMotionCFfPA2_f"),
|
||||||
Some("CFluidUVMotion::CalculateFluidTextureOffset(float, float(*)[2]) const".to_string())
|
Some(
|
||||||
|
"CFluidUVMotion::CalculateFluidTextureOffset(float, float(*)[2]) const".to_string()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
demangle("RenderNormals__FRA43_A43_CQ220CFluidPlaneCPURender13SHFieldSampleRA22_A22_CUcRCQ220CFluidPlaneCPURender10SPatchInfo"),
|
demangle("RenderNormals__FRA43_A43_CQ220CFluidPlaneCPURender13SHFieldSampleRA22_A22_CUcRCQ220CFluidPlaneCPURender10SPatchInfo"),
|
||||||
|
@ -463,5 +490,9 @@ mod tests {
|
||||||
demangle("Matrix__FfPA2_A3_f"),
|
demangle("Matrix__FfPA2_A3_f"),
|
||||||
Some("Matrix(float, float(*)[2][3])".to_string())
|
Some("Matrix(float, float(*)[2][3])".to_string())
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
demangle("__ct<12CStringTable>__31CObjOwnerDerivedFromIObjUntypedFRCQ24rstl24auto_ptr<12CStringTable>"),
|
||||||
|
Some("CObjOwnerDerivedFromIObjUntyped::CObjOwnerDerivedFromIObjUntyped<CStringTable>(const rstl::auto_ptr<CStringTable>&)".to_string())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue