com.wallstop-studios.unity-helpers 2.0.0-rc79.3 → 2.0.0-rc79.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/npm-publish.yml +2 -2
- package/Runtime/Core/Extension/IReadonlyListExtensions.cs +1 -1
- package/Runtime/Core/Extension/IReadonlyListExtensions.cs.meta +1 -1
- package/Runtime/Core/Extension/StringExtensions.cs +1 -1
- package/Runtime/Core/Helper/StringInList.cs +3 -21
- package/Runtime/Core/Threading/SingleThreadedThreadPool.cs +157 -49
- package/Runtime/Utils/Buffers.cs +118 -2
- package/Runtime/Utils/SevenZip/Common/CRC.cs +9 -0
- package/Runtime/Utils/SevenZip/Common/InBuffer.cs +15 -2
- package/Runtime/Utils/SevenZip/Common/OutBuffer.cs +7 -2
- package/Runtime/Utils/SevenZip/Compress/LZ/LzBinTree.cs +50 -0
- package/Runtime/Utils/SevenZip/Compress/LZ/LzInWindow.cs +26 -0
- package/Runtime/Utils/SevenZip/Compress/LZ/LzOutWindow.cs +27 -0
- package/Runtime/Utils/SevenZip/Compress/LZMA/LzmaBase.cs +9 -0
- package/Runtime/Utils/SevenZip/Compress/LZMA/LzmaDecoder.cs +80 -17
- package/Runtime/Utils/SevenZip/Compress/LZMA/LzmaEncoder.cs +265 -30
- package/Runtime/Utils/SevenZip/Compress/RangeCoder/RangeCoder.cs +9 -0
- package/Runtime/Utils/SevenZip/Compress/RangeCoder/RangeCoderBit.cs +13 -1
- package/Runtime/Utils/SevenZip/Compress/RangeCoder/RangeCoderBitTree.cs +11 -4
- package/Tests/Runtime/Core/Threading/SingleThreadedThreadPoolTests.cs +54 -0
- package/Tests/Runtime/Core/Threading/SingleThreadedThreadPoolTests.cs.meta +3 -0
- package/Tests/Runtime/Core/Threading.meta +3 -0
- package/Tests/Runtime/Core.meta +3 -0
- package/Tests/Runtime/DataStructures/BalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/CyclicBufferTests.cs +1 -1
- package/Tests/Runtime/DataStructures/QuadTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/SpatialTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/UnbalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/Extensions/DictionaryExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/EnumExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/IListExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/IReadonlyListExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/IReadonlyListExtensionTests.cs.meta +1 -1
- package/Tests/Runtime/Extensions/LoggingExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/RandomExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/StringExtensionTests.cs +1 -1
- package/Tests/Runtime/Helper/ObjectHelperTests.cs +1 -1
- package/Tests/Runtime/Helper/WallMathTests.cs +1 -1
- package/Tests/Runtime/Performance/KDTreePerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/QuadTreePerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/SpatialTreePerformanceTest.cs +1 -2
- package/Tests/Runtime/Performance/UnbalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/Random/RandomTestBase.cs +2 -2
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +1 -1
- package/Tests/Runtime/Utils/BuffersTests.cs +55 -0
- package/Tests/Runtime/Utils/BuffersTests.cs.meta +3 -0
- package/package.json +3 -1
package/.github/dependabot.yml
CHANGED
|
@@ -14,12 +14,12 @@ jobs:
|
|
|
14
14
|
|
|
15
15
|
steps:
|
|
16
16
|
- name: Checkout Repository
|
|
17
|
-
uses: actions/checkout@
|
|
17
|
+
uses: actions/checkout@v5
|
|
18
18
|
with:
|
|
19
19
|
fetch-depth: 0 # Ensure full commit history for version comparison
|
|
20
20
|
|
|
21
21
|
- name: Set up Node.js
|
|
22
|
-
uses: actions/setup-node@
|
|
22
|
+
uses: actions/setup-node@v5
|
|
23
23
|
with:
|
|
24
24
|
node-version: 18
|
|
25
25
|
registry-url: 'https://registry.npmjs.org/'
|
|
@@ -8,7 +8,7 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
|
|
|
8
8
|
|
|
9
9
|
public static class StringExtensions
|
|
10
10
|
{
|
|
11
|
-
private static ThreadLocal<StringBuilder> StringBuilderCache = new(() =>
|
|
11
|
+
private static readonly ThreadLocal<StringBuilder> StringBuilderCache = new(() =>
|
|
12
12
|
new StringBuilder()
|
|
13
13
|
);
|
|
14
14
|
|
|
@@ -6,21 +6,15 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
6
6
|
|
|
7
7
|
public sealed class StringInList : PropertyAttribute
|
|
8
8
|
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
private bool _shouldRefresh;
|
|
12
|
-
private string[] _list;
|
|
13
|
-
private Func<string[]> _getStringList;
|
|
9
|
+
private readonly Func<string[]> _getStringList;
|
|
14
10
|
|
|
15
11
|
public StringInList(params string[] list)
|
|
16
12
|
{
|
|
17
|
-
|
|
18
|
-
_list = list;
|
|
13
|
+
_getStringList = () => list;
|
|
19
14
|
}
|
|
20
15
|
|
|
21
16
|
public StringInList(Type type, string methodName)
|
|
22
17
|
{
|
|
23
|
-
_shouldRefresh = true;
|
|
24
18
|
MethodInfo method = type.GetMethod(
|
|
25
19
|
methodName,
|
|
26
20
|
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic
|
|
@@ -36,18 +30,6 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
32
|
|
|
39
|
-
public string[] List
|
|
40
|
-
{
|
|
41
|
-
get
|
|
42
|
-
{
|
|
43
|
-
if (_shouldRefresh)
|
|
44
|
-
{
|
|
45
|
-
return _getStringList();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return _list;
|
|
49
|
-
}
|
|
50
|
-
private set { _list = value; }
|
|
51
|
-
}
|
|
33
|
+
public string[] List => _getStringList();
|
|
52
34
|
}
|
|
53
35
|
}
|
|
@@ -3,116 +3,224 @@ namespace WallstopStudios.UnityHelpers.Core.Threading
|
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Concurrent;
|
|
5
5
|
using System.Threading;
|
|
6
|
+
using System.Threading.Tasks;
|
|
6
7
|
|
|
7
8
|
public sealed class SingleThreadedThreadPool : IDisposable
|
|
8
9
|
{
|
|
9
10
|
public ConcurrentQueue<Exception> Exceptions => _exceptions;
|
|
10
|
-
public int Count => _work.Count +
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
private
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
private
|
|
11
|
+
public int Count => _work.Count + (_isWorking ? 1 : 0);
|
|
12
|
+
|
|
13
|
+
private volatile bool _active = true;
|
|
14
|
+
private volatile bool _isWorking;
|
|
15
|
+
private volatile bool _disposed;
|
|
16
|
+
|
|
17
|
+
private readonly Task _workerTask;
|
|
18
|
+
private readonly ConcurrentQueue<WorkItem> _work;
|
|
19
|
+
private readonly SemaphoreSlim _workAvailable;
|
|
18
20
|
private readonly ConcurrentQueue<Exception> _exceptions;
|
|
19
21
|
private readonly TimeSpan _noWorkWaitTime;
|
|
22
|
+
private readonly CancellationTokenSource _cancellationTokenSource;
|
|
20
23
|
|
|
21
24
|
public SingleThreadedThreadPool(
|
|
22
|
-
bool runInBackground =
|
|
25
|
+
bool runInBackground = true,
|
|
23
26
|
TimeSpan? noWorkWaitTime = null
|
|
24
27
|
)
|
|
25
28
|
{
|
|
26
|
-
|
|
27
|
-
_working = 1;
|
|
28
|
-
_work = new ConcurrentQueue<Action>();
|
|
29
|
+
_work = new ConcurrentQueue<WorkItem>();
|
|
29
30
|
_exceptions = new ConcurrentQueue<Exception>();
|
|
30
|
-
|
|
31
|
+
_workAvailable = new SemaphoreSlim(0);
|
|
31
32
|
_noWorkWaitTime = noWorkWaitTime ?? TimeSpan.FromSeconds(1);
|
|
32
|
-
|
|
33
|
-
_worker.Start();
|
|
34
|
-
}
|
|
33
|
+
_cancellationTokenSource = new CancellationTokenSource();
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
_workerTask = runInBackground
|
|
36
|
+
? Task.Run(DoWorkAsync)
|
|
37
|
+
: Task.Factory.StartNew(DoWorkAsync, TaskCreationOptions.LongRunning).Unwrap();
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
public void Enqueue(Action work)
|
|
42
41
|
{
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
if (_disposed || !_active)
|
|
43
|
+
{
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
_work.Enqueue(WorkItem.FromAction(work));
|
|
48
|
+
Signal();
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
public void
|
|
51
|
+
public void Enqueue(Func<Task> work)
|
|
48
52
|
{
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
if (_disposed || !_active)
|
|
54
|
+
{
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_work.Enqueue(WorkItem.FromTask(work));
|
|
59
|
+
Signal();
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
public void
|
|
62
|
+
public void Enqueue(Func<ValueTask> work)
|
|
54
63
|
{
|
|
55
|
-
if (_disposed)
|
|
64
|
+
if (_disposed || !_active)
|
|
56
65
|
{
|
|
57
66
|
return;
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
|
|
69
|
+
_work.Enqueue(WorkItem.FromValueTask(work));
|
|
70
|
+
Signal();
|
|
71
|
+
}
|
|
61
72
|
|
|
62
|
-
|
|
73
|
+
private void Signal()
|
|
74
|
+
{
|
|
75
|
+
try
|
|
63
76
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// Swallow
|
|
72
|
-
}
|
|
77
|
+
_workAvailable.Release();
|
|
78
|
+
}
|
|
79
|
+
catch
|
|
80
|
+
{
|
|
81
|
+
// Swallow
|
|
82
|
+
}
|
|
83
|
+
}
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
public async ValueTask DisposeAsync()
|
|
86
|
+
{
|
|
87
|
+
if (_disposed)
|
|
88
|
+
{
|
|
89
|
+
return;
|
|
76
90
|
}
|
|
77
91
|
|
|
92
|
+
_active = false;
|
|
78
93
|
_disposed = true;
|
|
94
|
+
|
|
95
|
+
_cancellationTokenSource.Cancel();
|
|
96
|
+
Signal();
|
|
97
|
+
try
|
|
98
|
+
{
|
|
99
|
+
await _workerTask.ConfigureAwait(false);
|
|
100
|
+
}
|
|
101
|
+
catch (OperationCanceledException)
|
|
102
|
+
{
|
|
103
|
+
// Expected during shutdown
|
|
104
|
+
}
|
|
105
|
+
catch
|
|
106
|
+
{
|
|
107
|
+
// Swallow other exceptions during disposal
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_cancellationTokenSource?.Dispose();
|
|
111
|
+
_workAvailable?.Dispose();
|
|
112
|
+
|
|
113
|
+
GC.SuppressFinalize(this);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public void Dispose()
|
|
117
|
+
{
|
|
118
|
+
DisposeAsync().AsTask().GetAwaiter().GetResult();
|
|
79
119
|
}
|
|
80
120
|
|
|
81
|
-
private
|
|
121
|
+
private async Task DoWorkAsync()
|
|
82
122
|
{
|
|
83
|
-
|
|
123
|
+
CancellationToken cancellationToken = _cancellationTokenSource.Token;
|
|
124
|
+
|
|
125
|
+
while (_active && !cancellationToken.IsCancellationRequested)
|
|
84
126
|
{
|
|
85
127
|
try
|
|
86
128
|
{
|
|
87
|
-
if (_work.TryDequeue(out
|
|
129
|
+
if (_work.TryDequeue(out WorkItem workItem))
|
|
88
130
|
{
|
|
89
|
-
|
|
131
|
+
_isWorking = true;
|
|
90
132
|
try
|
|
91
133
|
{
|
|
92
|
-
workItem();
|
|
134
|
+
await workItem.ExecuteAsync().ConfigureAwait(false);
|
|
93
135
|
}
|
|
94
136
|
catch (Exception e)
|
|
95
137
|
{
|
|
96
138
|
_exceptions.Enqueue(e);
|
|
97
139
|
}
|
|
140
|
+
finally
|
|
141
|
+
{
|
|
142
|
+
_isWorking = false;
|
|
143
|
+
}
|
|
98
144
|
}
|
|
99
145
|
else
|
|
100
146
|
{
|
|
101
147
|
try
|
|
102
148
|
{
|
|
103
|
-
|
|
149
|
+
await _workAvailable
|
|
150
|
+
.WaitAsync(_noWorkWaitTime, cancellationToken)
|
|
151
|
+
.ConfigureAwait(false);
|
|
104
152
|
}
|
|
105
|
-
catch (
|
|
153
|
+
catch (OperationCanceledException)
|
|
106
154
|
{
|
|
107
|
-
|
|
155
|
+
break;
|
|
108
156
|
}
|
|
109
157
|
}
|
|
110
158
|
}
|
|
111
|
-
|
|
159
|
+
catch (ObjectDisposedException)
|
|
112
160
|
{
|
|
113
|
-
|
|
161
|
+
break;
|
|
114
162
|
}
|
|
115
163
|
}
|
|
116
164
|
}
|
|
165
|
+
|
|
166
|
+
private enum WorkItemType
|
|
167
|
+
{
|
|
168
|
+
Unknown = 0,
|
|
169
|
+
Action = 1,
|
|
170
|
+
Task = 2,
|
|
171
|
+
ValueTask = 3,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private readonly struct WorkItem
|
|
175
|
+
{
|
|
176
|
+
private readonly WorkItemType _type;
|
|
177
|
+
private readonly Action _action;
|
|
178
|
+
private readonly Func<Task> _taskFunc;
|
|
179
|
+
private readonly Func<ValueTask> _valueTaskFunc;
|
|
180
|
+
|
|
181
|
+
private WorkItem(
|
|
182
|
+
WorkItemType type,
|
|
183
|
+
Action action = null,
|
|
184
|
+
Func<Task> taskFunc = null,
|
|
185
|
+
Func<ValueTask> valueTaskFunc = null
|
|
186
|
+
)
|
|
187
|
+
{
|
|
188
|
+
_type = type;
|
|
189
|
+
_action = action;
|
|
190
|
+
_taskFunc = taskFunc;
|
|
191
|
+
_valueTaskFunc = valueTaskFunc;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public static WorkItem FromAction(Action action) =>
|
|
195
|
+
new(WorkItemType.Action, action: action);
|
|
196
|
+
|
|
197
|
+
public static WorkItem FromTask(Func<Task> taskFunc) =>
|
|
198
|
+
new(WorkItemType.Task, taskFunc: taskFunc);
|
|
199
|
+
|
|
200
|
+
public static WorkItem FromValueTask(Func<ValueTask> valueTaskFunc) =>
|
|
201
|
+
new(WorkItemType.ValueTask, valueTaskFunc: valueTaskFunc);
|
|
202
|
+
|
|
203
|
+
public ValueTask ExecuteAsync()
|
|
204
|
+
{
|
|
205
|
+
return _type switch
|
|
206
|
+
{
|
|
207
|
+
WorkItemType.Action => ExecuteAction(),
|
|
208
|
+
WorkItemType.Task => ExecuteTask(),
|
|
209
|
+
WorkItemType.ValueTask => _valueTaskFunc(),
|
|
210
|
+
_ => default,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private ValueTask ExecuteAction()
|
|
215
|
+
{
|
|
216
|
+
_action();
|
|
217
|
+
return default;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private async ValueTask ExecuteTask()
|
|
221
|
+
{
|
|
222
|
+
await _taskFunc().ConfigureAwait(false);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
117
225
|
}
|
|
118
226
|
}
|
package/Runtime/Utils/Buffers.cs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
namespace WallstopStudios.UnityHelpers.Utils
|
|
2
2
|
{
|
|
3
|
+
using System;
|
|
3
4
|
using System.Collections.Generic;
|
|
5
|
+
using System.Reflection;
|
|
4
6
|
using System.Text;
|
|
5
7
|
using UnityEngine;
|
|
6
8
|
|
|
@@ -27,11 +29,125 @@ namespace WallstopStudios.UnityHelpers.Utils
|
|
|
27
29
|
|
|
28
30
|
public static class Buffers<T>
|
|
29
31
|
{
|
|
30
|
-
public static readonly T[] Array = new T[Buffers.BufferSize];
|
|
31
32
|
public static readonly List<T> List = new();
|
|
32
33
|
public static readonly HashSet<T> HashSet = new();
|
|
33
34
|
public static readonly Queue<T> Queue = new();
|
|
34
35
|
public static readonly Stack<T> Stack = new();
|
|
35
|
-
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static class WallstopGenericPool<T>
|
|
39
|
+
where T : new()
|
|
40
|
+
{
|
|
41
|
+
private static readonly List<T> _pool = new();
|
|
42
|
+
private static readonly Action<T> _clearAction = GetClearAction();
|
|
43
|
+
private static readonly Action<T> _onDispose = Release;
|
|
44
|
+
|
|
45
|
+
public static PooledResource<T> Get()
|
|
46
|
+
{
|
|
47
|
+
if (_pool.Count == 0)
|
|
48
|
+
{
|
|
49
|
+
return new PooledResource<T>(new T(), _onDispose);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
int lastIndex = _pool.Count - 1;
|
|
53
|
+
T instance = _pool[lastIndex];
|
|
54
|
+
_pool.RemoveAt(lastIndex);
|
|
55
|
+
return new PooledResource<T>(instance, _onDispose);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private static Action<T> GetClearAction()
|
|
59
|
+
{
|
|
60
|
+
Type type = typeof(T);
|
|
61
|
+
foreach (
|
|
62
|
+
MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
|
|
63
|
+
)
|
|
64
|
+
{
|
|
65
|
+
if (
|
|
66
|
+
string.Equals(method.Name, "Clear", StringComparison.Ordinal)
|
|
67
|
+
&& method.GetParameters().Length == 0
|
|
68
|
+
)
|
|
69
|
+
{
|
|
70
|
+
return (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), method);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return _ => { };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private static void Release(T resource)
|
|
78
|
+
{
|
|
79
|
+
_clearAction.Invoke(resource);
|
|
80
|
+
_pool.Add(resource);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public static class WallstopArrayPool<T>
|
|
85
|
+
{
|
|
86
|
+
private static readonly Dictionary<int, List<T[]>> _pool = new();
|
|
87
|
+
private static readonly Action<T[]> _onDispose = Release;
|
|
88
|
+
|
|
89
|
+
public static PooledResource<T[]> Get(int size)
|
|
90
|
+
{
|
|
91
|
+
switch (size)
|
|
92
|
+
{
|
|
93
|
+
case < 0:
|
|
94
|
+
{
|
|
95
|
+
throw new ArgumentOutOfRangeException(
|
|
96
|
+
nameof(size),
|
|
97
|
+
size,
|
|
98
|
+
"Must be non-negative."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
case 0:
|
|
102
|
+
{
|
|
103
|
+
return new PooledResource<T[]>(Array.Empty<T>(), _ => { });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!_pool.TryGetValue(size, out List<T[]> pool))
|
|
108
|
+
{
|
|
109
|
+
pool = new List<T[]>();
|
|
110
|
+
_pool[size] = pool;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (pool.Count == 0)
|
|
114
|
+
{
|
|
115
|
+
return new PooledResource<T[]>(new T[size], _onDispose);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
int lastIndex = pool.Count - 1;
|
|
119
|
+
T[] instance = pool[lastIndex];
|
|
120
|
+
pool.RemoveAt(lastIndex);
|
|
121
|
+
return new PooledResource<T[]>(instance, _onDispose);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private static void Release(T[] resource)
|
|
125
|
+
{
|
|
126
|
+
int length = resource.Length;
|
|
127
|
+
Array.Clear(resource, 0, length);
|
|
128
|
+
if (!_pool.TryGetValue(length, out List<T[]> pool))
|
|
129
|
+
{
|
|
130
|
+
pool = new List<T[]>();
|
|
131
|
+
_pool[resource.Length] = pool;
|
|
132
|
+
}
|
|
133
|
+
pool.Add(resource);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public readonly struct PooledResource<T> : IDisposable
|
|
138
|
+
{
|
|
139
|
+
public readonly T resource;
|
|
140
|
+
private readonly Action<T> _onDispose;
|
|
141
|
+
|
|
142
|
+
internal PooledResource(T resource, Action<T> onDispose)
|
|
143
|
+
{
|
|
144
|
+
this.resource = resource;
|
|
145
|
+
_onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public void Dispose()
|
|
149
|
+
{
|
|
150
|
+
_onDispose(resource);
|
|
151
|
+
}
|
|
36
152
|
}
|
|
37
153
|
}
|
|
@@ -14,10 +14,17 @@ namespace SevenZip
|
|
|
14
14
|
{
|
|
15
15
|
uint r = i;
|
|
16
16
|
for (int j = 0; j < 8; j++)
|
|
17
|
+
{
|
|
17
18
|
if ((r & 1) != 0)
|
|
19
|
+
{
|
|
18
20
|
r = (r >> 1) ^ kPoly;
|
|
21
|
+
}
|
|
19
22
|
else
|
|
23
|
+
{
|
|
20
24
|
r >>= 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
Table[i] = r;
|
|
22
29
|
}
|
|
23
30
|
}
|
|
@@ -37,7 +44,9 @@ namespace SevenZip
|
|
|
37
44
|
public void Update(byte[] data, uint offset, uint size)
|
|
38
45
|
{
|
|
39
46
|
for (uint i = 0; i < size; i++)
|
|
47
|
+
{
|
|
40
48
|
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
|
|
49
|
+
}
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
public uint GetDigest()
|
|
@@ -4,10 +4,10 @@ namespace SevenZip.Buffer
|
|
|
4
4
|
{
|
|
5
5
|
public class InBuffer
|
|
6
6
|
{
|
|
7
|
-
byte[] m_Buffer;
|
|
7
|
+
readonly byte[] m_Buffer;
|
|
8
8
|
uint m_Pos;
|
|
9
9
|
uint m_Limit;
|
|
10
|
-
uint m_BufferSize;
|
|
10
|
+
readonly uint m_BufferSize;
|
|
11
11
|
System.IO.Stream m_Stream;
|
|
12
12
|
bool m_StreamWasExhausted;
|
|
13
13
|
ulong m_ProcessedSize;
|
|
@@ -30,7 +30,10 @@ namespace SevenZip.Buffer
|
|
|
30
30
|
public bool ReadBlock()
|
|
31
31
|
{
|
|
32
32
|
if (m_StreamWasExhausted)
|
|
33
|
+
{
|
|
33
34
|
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
34
37
|
m_ProcessedSize += m_Pos;
|
|
35
38
|
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
|
|
36
39
|
m_Pos = 0;
|
|
@@ -48,8 +51,13 @@ namespace SevenZip.Buffer
|
|
|
48
51
|
public bool ReadByte(byte b) // check it
|
|
49
52
|
{
|
|
50
53
|
if (m_Pos >= m_Limit)
|
|
54
|
+
{
|
|
51
55
|
if (!ReadBlock())
|
|
56
|
+
{
|
|
52
57
|
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
b = m_Buffer[m_Pos++];
|
|
54
62
|
return true;
|
|
55
63
|
}
|
|
@@ -58,8 +66,13 @@ namespace SevenZip.Buffer
|
|
|
58
66
|
{
|
|
59
67
|
// return (byte)m_Stream.ReadByte();
|
|
60
68
|
if (m_Pos >= m_Limit)
|
|
69
|
+
{
|
|
61
70
|
if (!ReadBlock())
|
|
71
|
+
{
|
|
62
72
|
return 0xFF;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
63
76
|
return m_Buffer[m_Pos++];
|
|
64
77
|
}
|
|
65
78
|
|
|
@@ -4,9 +4,9 @@ namespace SevenZip.Buffer
|
|
|
4
4
|
{
|
|
5
5
|
public class OutBuffer
|
|
6
6
|
{
|
|
7
|
-
byte[] m_Buffer;
|
|
7
|
+
readonly byte[] m_Buffer;
|
|
8
8
|
uint m_Pos;
|
|
9
|
-
uint m_BufferSize;
|
|
9
|
+
readonly uint m_BufferSize;
|
|
10
10
|
System.IO.Stream m_Stream;
|
|
11
11
|
ulong m_ProcessedSize;
|
|
12
12
|
|
|
@@ -46,13 +46,18 @@ namespace SevenZip.Buffer
|
|
|
46
46
|
{
|
|
47
47
|
m_Buffer[m_Pos++] = b;
|
|
48
48
|
if (m_Pos >= m_BufferSize)
|
|
49
|
+
{
|
|
49
50
|
FlushData();
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
public void FlushData()
|
|
53
55
|
{
|
|
54
56
|
if (m_Pos == 0)
|
|
57
|
+
{
|
|
55
58
|
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
m_Stream.Write(m_Buffer, 0, (int)m_Pos);
|
|
57
62
|
m_Pos = 0;
|
|
58
63
|
}
|