Skip to content

Commit 6143064

Browse files
authored
feat: expose Core.SimplifyNameToQualifiedName (Python parity, sret) (#37)
Closes HIGH missing-capi gap #24. The binding declared the BNRustSimplifyStrToFQN P/Invoke (which returns a BNQualifiedName by value) but declined to expose it: two TODO notes warned the struct-return (sret) ABI made the binding "non-trivial" and redirected callers to the string-only RustSimplifyStrToStr, so Python's demangle.simplify_name_to_qualified_name (demangle.py:253) had no managed equivalent. The sret concern was unfounded: BNQualifiedName is blittable (two IntPtrs plus a ulong), so the P/Invoke marshaller handles the struct-return ABI directly -- the same pattern as BNTypeBuilderGetStructureName. Verified end-to-end: a templated C++ name collapses identically to Python. Add Core.SimplifyNameToQualifiedName with a string overload (simplify flag, defaults true) and a QualifiedName overload (Python forces simplify=true for qualified-name input). Both wrap via QualifiedName.TakeNative (reads components eagerly, then frees the native array) and return null when the simplifier yields no components. Removes the two stale TODO notes.
1 parent 539cbf3 commit 6143064

1 file changed

Lines changed: 49 additions & 7 deletions

File tree

‎Misc/CoreUtils.cs‎

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -731,9 +731,55 @@ public static string RustSimplifyStrToStr(string name)
731731
);
732732
}
733733

734-
// NOTE: BNRustSimplifyStrToFQN uses sret (struct return) calling convention
735-
// which makes the P/Invoke binding non-trivial. Use RustSimplifyStrToStr
736-
// for simple string simplification instead.
734+
/// <summary>
735+
/// Simplifies a templated C++ name to a qualified name, mirroring Python
736+
/// <c>demangle.simplify_name_to_qualified_name</c> (demangle.py:253). This can also tokenize a
737+
/// string to a qualified name without simplifying. Returns <c>null</c> when the simplifier
738+
/// yields no components.
739+
/// </summary>
740+
/// <param name="inputName">The name to simplify.</param>
741+
/// <param name="simplify">Whether to simplify the name; defaults to <c>true</c>.</param>
742+
/// <returns>The simplified qualified name, or <c>null</c> if the result is empty.</returns>
743+
public static QualifiedName? SimplifyNameToQualifiedName(string inputName, bool simplify = true)
744+
{
745+
if (null == inputName)
746+
{
747+
throw new ArgumentNullException(nameof(inputName));
748+
}
749+
750+
// BNRustSimplifyStrToFQN returns a BNQualifiedName by value. The struct is blittable
751+
// (two IntPtrs + a ulong), so the P/Invoke marshaller handles the struct-return (sret)
752+
// ABI directly -- the same pattern as BNTypeBuilderGetStructureName. TakeNative reads the
753+
// components eagerly then frees the native array the core allocated.
754+
QualifiedName result = QualifiedName.TakeNative(
755+
NativeMethods.BNRustSimplifyStrToFQN(inputName, simplify)
756+
);
757+
758+
if (0 == result.Name.Length)
759+
{
760+
return null;
761+
}
762+
763+
return result;
764+
}
765+
766+
/// <summary>
767+
/// Simplifies an already-tokenized qualified name, mirroring Python
768+
/// <c>demangle.simplify_name_to_qualified_name</c> for <c>QualifiedName</c> input
769+
/// (demangle.py:267). Python forces simplification for qualified-name input, so
770+
/// <paramref name="inputName"/> is always simplified.
771+
/// </summary>
772+
/// <param name="inputName">The qualified name to simplify.</param>
773+
/// <returns>The simplified qualified name, or <c>null</c> if the result is empty.</returns>
774+
public static QualifiedName? SimplifyNameToQualifiedName(QualifiedName inputName)
775+
{
776+
if (null == inputName)
777+
{
778+
throw new ArgumentNullException(nameof(inputName));
779+
}
780+
781+
return Core.SimplifyNameToQualifiedName(inputName.ToString(), true);
782+
}
737783

738784
/// <summary>
739785
/// Compute a fuzzy match score between a target string and a query.
@@ -1170,10 +1216,6 @@ public static unsafe string[] ParseTypeParserOptionsText(string optionsText)
11701216
// TODO: BNRenderLinesForData / BNGetLinesForData — complex callback-based renderer
11711217
// with custom data renderer context callback parameters.
11721218

1173-
// TODO: BNRustSimplifyStrToFQN — uses sret ABI (struct return by hidden pointer).
1174-
// The BNQualifiedName return value is passed as a hidden first parameter;
1175-
// requires special P/Invoke marshalling or a C wrapper to implement correctly.
1176-
11771219
// TODO: BNAppendSymbolQueue / BNProcessSymbolQueue — internal callback-based
11781220
// symbol resolution pipeline. Requires managed delegate infrastructure.
11791221

0 commit comments

Comments
 (0)