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
+1 -4
View File
@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -35,10 +34,8 @@ public static class BenchData
/// <summary>
/// The save decoded as text for the regex engines.
/// Latin1 is used because EU4 saves contain non-UTF8 bytes inside dynasty names,
/// and it maps every byte to exactly one char.
/// </summary>
public static string PdxText => _pdxText ??= Encoding.Latin1.GetString(PdxBytes);
public static string PdxText => _pdxText ??= SaveParserEU4.DefaultEncoding.GetString(PdxBytes);
private static string FindRepoRoot()
{
@@ -18,7 +18,7 @@ public class ExtractionBenchmarks
private byte[] _pdx = null!;
private string _pdxText = null!;
private byte[] _json = null!;
private ISearchExpression _query = null!;
private SearchExpressionCompilation _query = null!;
private Regex _technologyBlock = null!;
private Regex _pathAwareCompiled = null!;
@@ -32,7 +32,7 @@ public class ExtractionBenchmarks
_pdx = BenchData.PdxBytes;
_pdxText = BenchData.PdxText;
_json = File.ReadAllBytes(BenchData.JsonPath);
_query = SearchExpressionCompiler.Compile(BenchData.PdxQuery);
_query = new SearchExpressionCompilation(BenchData.PdxQuery);
_technologyBlock = new Regex(Extractors.TechnologyBlockPattern, RegexOptions.Compiled);
_pathAwareCompiled = new Regex(Extractors.PathAwarePattern, RegexOptions.Compiled);
+2 -2
View File
@@ -22,7 +22,7 @@ public static partial class Extractors
// ---------------------------------------------------------------- this project
/// <summary>The parser of this repo: single streaming pass, guided by a compiled search expression.</summary>
public static long SearchExpression(byte[] pdx, ISearchExpression query)
public static long SearchExpression(byte[] pdx, SearchExpressionCompilation query)
{
using var stream = new MemoryStream(pdx, false);
var root = new SaveParserEU4(stream, query).Parse();
@@ -30,7 +30,7 @@ public static partial class Extractors
}
/// <summary>Same query, but the parser reads from the given stream instead of a preloaded byte[].</summary>
public static long SearchExpressionFromStream(Stream stream, ISearchExpression query)
public static long SearchExpressionFromStream(Stream stream, SearchExpressionCompilation query)
{
var root = new SaveParserEU4(stream, query).Parse();
return ChecksumOfParsedTree(root);
+1 -1
View File
@@ -18,7 +18,7 @@ public static class Mispairing
{
var result = new Dictionary<string, long>();
using var stream = new MemoryStream(pdx, false);
var root = new SaveParserEU4(stream, SearchExpressionCompiler.Compile(BenchData.PdxQuery)).Parse();
var root = new SaveParserEU4(stream, new SearchExpressionCompilation(BenchData.PdxQuery)).Parse();
foreach (var (tag, value) in (Dictionary<string, object>)root["countries"])
{
if (value is Dictionary<string, object> c
@@ -15,10 +15,10 @@ namespace ParadoxSaveParser.Benchmarks;
[SimpleJob(RunStrategy.Monitoring, launchCount: 1, warmupCount: 1, iterationCount: 5)]
public class ParserInputBenchmarks
{
private ISearchExpression _query = null!;
private SearchExpressionCompilation _query = null!;
[GlobalSetup]
public void Setup() => _query = SearchExpressionCompiler.Compile(BenchData.PdxQuery);
public void Setup() => _query = new SearchExpressionCompilation(BenchData.PdxQuery);
[Benchmark(Description = "SearchExpression over FileStream")]
public long FromFile()
+1 -1
View File
@@ -39,7 +39,7 @@ public static class Program
var pdx = BenchData.PdxBytes;
var text = BenchData.PdxText;
var json = File.ReadAllBytes(BenchData.JsonPath);
var query = SearchExpressionCompiler.Compile(BenchData.PdxQuery);
var query = new SearchExpressionCompilation(BenchData.PdxQuery);
Time("SearchExpression", () => Extractors.SearchExpression(pdx, query));
Time("FullParse", () => Extractors.FullParseThenSelect(pdx));