refactored SearchExpression

This commit is contained in:
2026-09-15 13:18:09 +02:00
parent 1d53f6930a
commit 5b1b8f4ce5
21 changed files with 509 additions and 216 deletions
@@ -0,0 +1,50 @@
namespace ParadoxSaveParser.Lib;
/// <summary>
/// One step of a compiled query. Each step points at the step its matched nodes
/// are searched with, so the query runs in a single pass down the tree.
/// </summary>
public interface ISearchExpression
{
/// <summary>Tests one node against this step of the query.</summary>
/// <param name="candidate">The node being tested, identified by its key or its position.</param>
/// <param name="nextSearchExpression">
/// On a match, the step for the node's children, or <c>null</c> if the node is kept whole.
/// Undefined when the method returns <c>false</c>.
/// </param>
/// <returns>true if the node is selected by this step</returns>
bool DoesMatch(MatchCandidate candidate, out ISearchExpression? nextSearchExpression);
/// <summary>
/// Encodes the literal keys of this step and of every step below it.
/// Called by <see cref="SearchExpressionCompilation" />, never during matching.
/// </summary>
void ReEncode(Encoding encoding);
}
/// <summary>
/// A node the query is tested against: its raw key and its position in the parent.
/// The key stays undecoded, so a rejected key never becomes a string.
/// </summary>
public readonly ref struct MatchCandidate
{
/// <summary>Undecoded key of the node. Empty for list items.</summary>
public readonly ReadOnlySpan<byte> Key;
/// <summary>Position of the node among its siblings, counted from 0.</summary>
public readonly int Index;
/// <summary>A list item, which has a position but no key.</summary>
public MatchCandidate(int index)
{
Key = default;
Index = index;
}
/// <summary>A dictionary entry, which has both a key and a position.</summary>
public MatchCandidate(int index, ReadOnlySpan<byte> key)
{
Key = key;
Index = index;
}
}