Skip to content

Commit 8fc071d

Browse files
committed
Better modernization of Blast
1 parent 97a83b4 commit 8fc071d

File tree

3 files changed

+77
-66
lines changed

3 files changed

+77
-66
lines changed

SabreTools.Compression/Blast/Decompressor.cs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public bool CopyTo(Stream source, Stream dest)
146146
int err;
147147
try
148148
{
149-
err = Decomp(state);
149+
err = Decompress(state);
150150
}
151151
catch (IndexOutOfRangeException)
152152
{
@@ -198,7 +198,7 @@ public bool CopyTo(Stream source, Stream dest)
198198
/// ignoring whether the length is greater than the distance or not implements
199199
/// this correctly.
200200
/// </remarks>
201-
private int Decomp(State state)
201+
private int Decompress(State state)
202202
{
203203
int symbol; // decoded symbol, extra bits for distance
204204
int len; // length for copy
@@ -207,37 +207,37 @@ private int Decomp(State state)
207207
int from, to; // copy pointers
208208

209209
// Read header
210-
int lit = state.Bits(8); // true if literals are coded
210+
int lit = state.ReadBits(8); // true if literals are coded
211211
if (lit > 1)
212212
return -1;
213213

214-
int dict = state.Bits(8); // log2(dictionary size) - 6
214+
int dict = state.ReadBits(8); // log2(dictionary size) - 6
215215
if (dict < 4 || dict > 6)
216216
return -2;
217217

218218
// Decode literals and length/distance pairs
219219
while (true)
220220
{
221-
if (state.Bits(1) != 0)
221+
if (state.ReadBits(1) != 0)
222222
{
223223
// Get length
224224
symbol = lencode.Decode(state);
225-
len = baseLength[symbol] + state.Bits(extra[symbol]);
225+
len = baseLength[symbol] + state.ReadBits(extra[symbol]);
226226
if (len == 519)
227227
break; // end code
228228

229229
// Get distance
230230
symbol = len == 2 ? 2 : dict;
231231
dist = (uint)(distcode.Decode(state) << symbol);
232-
dist += (uint)state.Bits(symbol);
232+
dist += (uint)state.ReadBits(symbol);
233233
dist++;
234234
if (state.First && dist > state.Next)
235235
return -3; //distance too far back
236236

237237
// Copy length bytes from distance bytes back
238238
do
239239
{
240-
to = (int)(state.OutputPtr + state.Next);
240+
to = (int)state.Next;
241241
from = (int)(to - dist);
242242
copy = MAXWIN;
243243
if (state.Next < dist)
@@ -252,11 +252,7 @@ private int Decomp(State state)
252252

253253
len -= copy;
254254
state.Next += (uint)copy;
255-
do
256-
{
257-
state.Output[to++] = state.Output[from++];
258-
}
259-
while (--copy != 0);
255+
state.CopyOutputBytes(to, from, copy);
260256

261257
if (state.Next == MAXWIN)
262258
{
@@ -272,8 +268,8 @@ private int Decomp(State state)
272268
else
273269
{
274270
// Get literal and write it
275-
symbol = lit != 0 ? litcode.Decode(state) : state.Bits(8);
276-
state.Output[state.Next++] = (byte)symbol;
271+
symbol = lit != 0 ? litcode.Decode(state) : state.ReadBits(8);
272+
state.WriteToOutput((byte)symbol);
277273
if (state.Next == MAXWIN)
278274
{
279275
if (!state.ProcessOutput())

SabreTools.Compression/Blast/Huffman.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using static SabreTools.Compression.Blast.Constants;
32

43
namespace SabreTools.Compression.Blast
@@ -187,15 +186,7 @@ public int Decode(State state)
187186
if (left == 0)
188187
break;
189188

190-
if (state.Left == 0)
191-
{
192-
state.Left = state.ProcessInput();
193-
if (state.Left == 0)
194-
throw new IndexOutOfRangeException();
195-
}
196-
197-
bitbuf = state.Input[state.InputPtr++];
198-
state.Left--;
189+
bitbuf = state.ReadNextByte();
199190
if (left > 8)
200191
left = 8;
201192
}

SabreTools.Compression/Blast/State.cs

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,22 @@ public class State
1414
/// <summary>
1515
/// Opaque information passed to InputFunction()
1616
/// </summary>
17-
public Stream Source { get; set; }
18-
17+
private readonly Stream _source;
18+
1919
/// <summary>
2020
/// Next input location
2121
/// </summary>
22-
public byte[] Input { get; set; }
22+
private readonly byte[] _input = new byte[MAXWIN];
2323

2424
/// <summary>
2525
/// Pointer to the next input location
2626
/// </summary>
27-
public int InputPtr { get; set; }
27+
private int _inputPtr;
2828

2929
/// <summary>
3030
/// Available input at in
3131
/// </summary>
32-
public uint Left { get; set; }
32+
private uint _available;
3333

3434
/// <summary>
3535
/// Bit buffer
@@ -48,7 +48,7 @@ public class State
4848
/// <summary>
4949
/// Opaque information passed to OutputFunction()
5050
/// </summary>
51-
public Stream Dest { get; set; }
51+
private readonly Stream _dest;
5252

5353
/// <summary>
5454
/// Index of next write location in out[]
@@ -63,12 +63,7 @@ public class State
6363
/// <summary>
6464
/// Output buffer and sliding window
6565
/// </summary>
66-
public readonly byte[] Output = new byte[MAXWIN];
67-
68-
/// <summary>
69-
/// Pointer to the next output location
70-
/// </summary>
71-
public int OutputPtr { get; set; }
66+
private readonly byte[] _output = new byte[MAXWIN];
7267

7368
#endregion
7469

@@ -77,18 +72,29 @@ public class State
7772
/// </summary>
7873
public State(Stream source, Stream dest)
7974
{
80-
Source = source;
81-
Input = [];
82-
InputPtr = 0;
83-
Left = 0;
75+
_source = source;
76+
_inputPtr = 0;
77+
_available = 0;
8478
BitBuf = 0;
8579
BitCnt = 0;
8680

87-
Dest = dest;
81+
_dest = dest;
8882
Next = 0;
8983
First = true;
9084
}
9185

86+
/// <summary>
87+
/// Copy bytes in the output buffer between locations
88+
/// </summary>
89+
public void CopyOutputBytes(int to, int from, int len)
90+
{
91+
do
92+
{
93+
_output[to++] = _output[from++];
94+
}
95+
while (--len > 0);
96+
}
97+
9298
/// <summary>
9399
/// Return need bits from the input stream. This always leaves less than
94100
/// eight bits in the buffer. bits() works properly for need == 0.
@@ -100,22 +106,16 @@ public State(Stream source, Stream dest)
100106
/// buffer, using shift right, and new bytes are appended to the top of the
101107
/// bit buffer, using shift left.
102108
/// </remarks>
103-
public int Bits(int need)
109+
public int ReadBits(int need)
104110
{
105111
// Load at least need bits into val
106112
int val = BitBuf;
107113
while (BitCnt < need)
108114
{
109-
if (Left == 0)
110-
{
111-
Left = ProcessInput();
112-
if (Left == 0)
113-
throw new IndexOutOfRangeException();
114-
}
115-
116115
// Load eight bits
117-
val |= Input[InputPtr++] << BitCnt;
118-
Left--;
116+
EnsureAvailable();
117+
val |= _input[_inputPtr++] << BitCnt;
118+
_available--;
119119
BitCnt += 8;
120120
}
121121

@@ -127,16 +127,6 @@ public int Bits(int need)
127127
return val & ((1 << need) - 1);
128128
}
129129

130-
/// <summary>
131-
/// Process input for the current state
132-
/// </summary>
133-
/// <returns>Amount of data in Input</returns>
134-
public uint ProcessInput()
135-
{
136-
int read = Source.Read(Input, 0, 4096);
137-
return (uint)read;
138-
}
139-
140130
/// <summary>
141131
/// Process output for the current state
142132
/// </summary>
@@ -145,16 +135,50 @@ public bool ProcessOutput()
145135
{
146136
try
147137
{
148-
byte[] next = new byte[Next];
149-
Array.Copy(Output, next, next.Length);
150-
Dest.Write(next);
151-
Dest.Flush();
138+
_dest.Write(_output, 0, (int)Next);
139+
_dest.Flush();
140+
141+
Next = 0;
152142
return true;
153143
}
154144
catch
155145
{
156146
return false;
157147
}
158148
}
149+
150+
/// <summary>
151+
/// Read the next byte from the input buffer
152+
/// </summary>
153+
public byte ReadNextByte()
154+
{
155+
EnsureAvailable();
156+
return _input[_inputPtr++];
157+
}
158+
159+
/// <summary>
160+
/// Write a byte value to the output buffer
161+
/// </summary>
162+
public void WriteToOutput(byte value)
163+
=> _output[Next++] = value;
164+
165+
/// <summary>
166+
/// Ensure there are bytes available, if possible
167+
/// </summary>
168+
/// <exception cref="IndexOutOfRangeException"></exception>
169+
private void EnsureAvailable()
170+
{
171+
// If there are bytes
172+
if (_inputPtr < _available)
173+
return;
174+
175+
// Read the next block
176+
_available = (uint)_source.Read(_input, 0, MAXWIN);
177+
if (_available == 0)
178+
throw new IndexOutOfRangeException();
179+
180+
// Reset the pointer
181+
_inputPtr = 0;
182+
}
159183
}
160184
}

0 commit comments

Comments
 (0)