diff --git a/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj new file mode 100644 index 0000000..6a8e78d --- /dev/null +++ b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj @@ -0,0 +1,19 @@ + + + Exe + net8.0 + latest + enable + disable + true + true + + + + + + + + + + diff --git a/ParadoxSaveParser.CLI/Program.cs b/ParadoxSaveParser.CLI/Program.cs new file mode 100644 index 0000000..918313a --- /dev/null +++ b/ParadoxSaveParser.CLI/Program.cs @@ -0,0 +1,108 @@ +global using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using DTLib.Console; +using DTLib.Demystifier; +using DTLib.Filesystem; +using ParadoxSaveParser.Lib; +using File = DTLib.Filesystem.File; +using Directory = DTLib.Filesystem.Directory; + +namespace ParadoxSaveParser.CLI; + +[JsonSourceGenerationOptions(MaxDepth = 1024, WriteIndented = true)] +[JsonSerializable(typeof(Dictionary>))] +[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(long))] +[JsonSerializable(typeof(double))] +public partial class ParsedValueJsonContext : JsonSerializerContext +{ +} + +class Program +{ + private static IOPath? _inputPath; + private static IOPath? _outputPath; + private static string? _searchQuery; + + static void Main(string[] args) + { + try + { + new LaunchArgumentParser( + new LaunchArgument(["-i", "--input"], + "Set input file path", + s => _inputPath = s, + "gamestate or zip file"), + + new LaunchArgument(["-o", "--output"], + "Set output file path", + s => _outputPath = s, + "json file [default=stdout]"), + + new LaunchArgument(["-s", "--search"], + "Search expression", + Search), + + new LaunchArgument(["-e", "--search-expression"], + "Set search expression", + s => _searchQuery = s, + "expression in my custom format" + ) + ) + .WithNoExit() + .ParseAndHandle(args); + + Console.Clear(); + Console.ResetColor(); + ColoredConsole.WriteTitle("interactive mode", fg: ConsoleColor.Cyan); + ColoredConsole.WriteLine($"working directory: '{Environment.CurrentDirectory}'", ConsoleColor.Gray); + + string? input = null; + for (int i = 0; i < 10 && string.IsNullOrEmpty(input); i++) + input = ColoredConsole.ReadLine("input file", ConsoleColor.Blue); + _inputPath = input ?? throw new NullReferenceException(); + + input = ColoredConsole.ReadLine("output file [default=stdout]", ConsoleColor.Blue); + if (!string.IsNullOrEmpty(input)) + _outputPath = input; + + _searchQuery = ColoredConsole.ReadLine("search expression", ConsoleColor.Blue); + + ColoredConsole.WriteHLine('-', ConsoleColor.Cyan); + Console.ResetColor(); + + Search(); + } + catch (Exception ex) + { + ColoredConsole.WriteLine(ex.ToStringDemystified(), ConsoleColor.Red); + Console.ResetColor(); + Environment.Exit(1); + } + Console.ResetColor(); + } + + private static void Search() + { + if(_inputPath == null) + throw new ArgumentException("Input file path is required"); + using var inputStream = File.OpenRead(_inputPath.Value); + + using var outputStream = _outputPath is null + ? Console.OpenStandardOutput() + : File.OpenWrite(_outputPath.Value); + + var searchExpression = string.IsNullOrEmpty(_searchQuery) + ? null + : SearchExpressionCompiler.Compile(_searchQuery); + var parser = new SaveParserEU4(inputStream, searchExpression); + var parsedValue = parser.Parse(); + JsonSerializer.Serialize(outputStream, parsedValue, ParsedValueJsonContext.Default.DictionaryStringListObject); + } +} \ No newline at end of file diff --git a/ParadoxSaveParser.Lib.Tests/ParadoxSaveParser.Lib.Tests.csproj b/ParadoxSaveParser.Lib.Tests/ParadoxSaveParser.Lib.Tests.csproj index b167bad..9ff7564 100644 --- a/ParadoxSaveParser.Lib.Tests/ParadoxSaveParser.Lib.Tests.csproj +++ b/ParadoxSaveParser.Lib.Tests/ParadoxSaveParser.Lib.Tests.csproj @@ -1,29 +1,35 @@ - net8.0 - enable + latest enable + disable + true false true - - - - - - + - + - + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - diff --git a/ParadoxSaveParser.Lib.Tests/SearchExpressionTests.cs b/ParadoxSaveParser.Lib.Tests/SearchExpressionTests.cs index 12453b3..ff04c03 100644 --- a/ParadoxSaveParser.Lib.Tests/SearchExpressionTests.cs +++ b/ParadoxSaveParser.Lib.Tests/SearchExpressionTests.cs @@ -1,3 +1,4 @@ +using System.IO; using System.Text.Encodings.Web; using System.Text.Json; using DTLib.Extensions; diff --git a/ParadoxSaveParser.Lib/ParadoxSaveParser.Lib.csproj b/ParadoxSaveParser.Lib/ParadoxSaveParser.Lib.csproj index 00ebf29..1b4b7a1 100644 --- a/ParadoxSaveParser.Lib/ParadoxSaveParser.Lib.csproj +++ b/ParadoxSaveParser.Lib/ParadoxSaveParser.Lib.csproj @@ -1,11 +1,13 @@  net8.0 - disable + latest enable + disable + true + - diff --git a/ParadoxSaveParser.sln b/ParadoxSaveParser.sln index 9034b81..b8cac23 100644 --- a/ParadoxSaveParser.sln +++ b/ParadoxSaveParser.sln @@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFolder", "SolutionF EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParadoxSaveParser.Lib.Tests", "ParadoxSaveParser.Lib.Tests\ParadoxSaveParser.Lib.Tests.csproj", "{23F4BE1B-3043-4821-9F65-74FF5F57FA59}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParadoxSaveParser.CLI", "ParadoxSaveParser.CLI\ParadoxSaveParser.CLI.csproj", "{2D4448A6-390D-47F3-9BB7-6266669719DE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,5 +32,9 @@ Global {23F4BE1B-3043-4821-9F65-74FF5F57FA59}.Debug|Any CPU.Build.0 = Debug|Any CPU {23F4BE1B-3043-4821-9F65-74FF5F57FA59}.Release|Any CPU.ActiveCfg = Release|Any CPU {23F4BE1B-3043-4821-9F65-74FF5F57FA59}.Release|Any CPU.Build.0 = Release|Any CPU + {2D4448A6-390D-47F3-9BB7-6266669719DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D4448A6-390D-47F3-9BB7-6266669719DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D4448A6-390D-47F3-9BB7-6266669719DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D4448A6-390D-47F3-9BB7-6266669719DE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/TODO.txt b/TODO.txt index 3166d2e..8ff0070 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,11 +1,14 @@ +Parser.CLI: + Temp files management system + Main: - Add temporary files deletion + Temp files management system + Database??? + Add query to get parsed data ParseSaveHandler: Make this method run as background task instead of POST query Add debug log - Save parsed in protobuf + Save parsed data in protobuf Re-parse if saved data was parsed with another query - -Parser: - Optimize it (5 sec per query isn't good) +