-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSessionResultStore.cs
More file actions
128 lines (111 loc) · 4.12 KB
/
Copy pathSessionResultStore.cs
File metadata and controls
128 lines (111 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System.Text;
namespace LuaDecompilerDesktop;
internal sealed record SessionResult(
string TempPath,
int CharacterCount,
int ConvertedSegments);
internal sealed class SessionResultStore : IDisposable
{
private readonly Dictionary<string, SessionResult> _results = new(StringComparer.OrdinalIgnoreCase);
private readonly string _tempRoot = Path.Combine(Path.GetTempPath(), "LuaDecompiler");
private readonly string _sessionDirectory;
private int _nextFileNumber;
private bool _disposed;
public SessionResultStore()
{
_sessionDirectory = Path.Combine(
_tempRoot,
$"session-{Environment.ProcessId}-{Guid.NewGuid():N}");
}
public int Count => _results.Count;
public string SessionDirectory => _sessionDirectory;
public bool Contains(string inputPath) => _results.ContainsKey(inputPath);
public bool TryGet(string inputPath, out SessionResult result) =>
_results.TryGetValue(inputPath, out result!);
public async Task<SessionResult> StoreAsync(
string inputPath,
string text,
int convertedSegments,
CancellationToken cancellationToken)
{
if (_disposed) throw new ObjectDisposedException(nameof(SessionResultStore));
var tempPath = CreateResultPath();
await File.WriteAllTextAsync(tempPath, text, new UTF8Encoding(false), cancellationToken);
return RegisterResult(inputPath, tempPath, text.Length, convertedSegments);
}
public string CreateResultPath()
{
if (_disposed) throw new ObjectDisposedException(nameof(SessionResultStore));
Directory.CreateDirectory(_sessionDirectory);
return Path.Combine(
_sessionDirectory,
$"result-{Interlocked.Increment(ref _nextFileNumber):D6}.lua");
}
public SessionResult RegisterResult(
string inputPath,
string tempPath,
int characterCount,
int convertedSegments)
{
if (_disposed) throw new ObjectDisposedException(nameof(SessionResultStore));
var stored = new SessionResult(tempPath, characterCount, convertedSegments);
if (_results.TryGetValue(inputPath, out var previous)
&& !string.Equals(previous.TempPath, tempPath, StringComparison.OrdinalIgnoreCase))
TryDeleteFile(previous.TempPath);
_results[inputPath] = stored;
return stored;
}
public void Remove(string inputPath)
{
if (!_results.Remove(inputPath, out var previous)) return;
TryDeleteFile(previous.TempPath);
}
public void DiscardFile(string path) => TryDeleteFile(path);
public void CopyTo(string inputPath, string outputPath)
{
if (!_results.TryGetValue(inputPath, out var result))
throw new InvalidOperationException("找不到本次会话的反编译结果。");
File.Copy(result.TempPath, outputPath, true);
}
public void Clear()
{
_results.Clear();
DeleteSessionDirectory();
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_results.Clear();
DeleteSessionDirectory();
}
private void DeleteSessionDirectory()
{
try
{
if (!Directory.Exists(_sessionDirectory)) return;
var fullSession = Path.GetFullPath(_sessionDirectory)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var fullRoot = Path.GetFullPath(_tempRoot)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
+ Path.DirectorySeparatorChar;
if (!fullSession.StartsWith(fullRoot, StringComparison.OrdinalIgnoreCase)) return;
Directory.Delete(fullSession, true);
}
catch
{
// 临时目录清理失败时不阻止程序退出;系统稍后仍可回收。
}
}
private static void TryDeleteFile(string path)
{
try
{
if (File.Exists(path)) File.Delete(path);
}
catch
{
// 旧会话结果稍后随整个临时目录一起清理。
}
}
}