Support template args for built-in operators

This commit is contained in:
Luke Street 2022-09-03 12:48:42 -04:00
parent 5318f6ac53
commit 64265e9efb
1 changed files with 77 additions and 46 deletions

View File

@ -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())
);
} }
} }