Included attribution
This commit is contained in:
@@ -5,6 +5,9 @@
|
|||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
* see LICENSE.
|
* see LICENSE.
|
||||||
|
*
|
||||||
|
* This file is based on the blast routines (version 1.1 by Mark Adler)
|
||||||
|
* included in zlib/contrib
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -13,92 +16,11 @@ using System.IO;
|
|||||||
|
|
||||||
namespace OpenRA.FileFormats
|
namespace OpenRA.FileFormats
|
||||||
{
|
{
|
||||||
// A reimplementation of the Blast routines included in zlib
|
|
||||||
public static class Blast
|
public static class Blast
|
||||||
{
|
{
|
||||||
public static readonly int MAXBITS = 13; // maximum code length
|
public static readonly int MAXBITS = 13; // maximum code length
|
||||||
public static readonly int MAXWIN = 4096; // maximum window size
|
public static readonly int MAXWIN = 4096; // maximum window size
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode a code from the stream s using huffman table h. Return the symbol or
|
|
||||||
* a negative value if there is an error. If all of the lengths are zero, i.e.
|
|
||||||
* an empty code, or if the code is incomplete and an invalid code is received,
|
|
||||||
* then -9 is returned after reading MAXBITS bits.
|
|
||||||
*
|
|
||||||
* Format notes:
|
|
||||||
*
|
|
||||||
* - The codes as stored in the compressed data are bit-reversed relative to
|
|
||||||
* a simple integer ordering of codes of the same lengths. Hence below the
|
|
||||||
* bits are pulled from the compressed data one at a time and used to
|
|
||||||
* build the code value reversed from what is in the stream in order to
|
|
||||||
* permit simple integer comparisons for decoding.
|
|
||||||
*
|
|
||||||
* - The first code for the shortest length is all ones. Subsequent codes of
|
|
||||||
* the same length are simply integer decrements of the previous code. When
|
|
||||||
* moving up a length, a one bit is appended to the code. For a complete
|
|
||||||
* code, the last code of the longest length will be all zeros. To support
|
|
||||||
* this ordering, the bits pulled during decoding are inverted to apply the
|
|
||||||
* more "natural" ordering starting with all zeros and incrementing.
|
|
||||||
*/
|
|
||||||
private static int Decode(Huffman h, BitReader br)
|
|
||||||
{
|
|
||||||
int code = 0; // len bits being decoded
|
|
||||||
int first = 0; // first code of length len
|
|
||||||
int index = 0; // index of first code of length len in symbol table
|
|
||||||
short next = 1;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
code |= br.ReadBits(1) ^ 1; // invert code
|
|
||||||
int count = h.Count[next++];
|
|
||||||
if (code < first + count)
|
|
||||||
return h.Symbol[index + (code - first)];
|
|
||||||
|
|
||||||
index += count;
|
|
||||||
first += count;
|
|
||||||
first <<= 1;
|
|
||||||
code <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode PKWare Compression Library stream.
|
|
||||||
*
|
|
||||||
* Format notes:
|
|
||||||
*
|
|
||||||
* - First byte is 0 if literals are uncoded or 1 if they are coded. Second
|
|
||||||
* byte is 4, 5, or 6 for the number of extra bits in the distance code.
|
|
||||||
* This is the base-2 logarithm of the dictionary size minus six.
|
|
||||||
*
|
|
||||||
* - Compressed data is a combination of literals and length/distance pairs
|
|
||||||
* terminated by an end code. Literals are either Huffman coded or
|
|
||||||
* uncoded bytes. A length/distance pair is a coded length followed by a
|
|
||||||
* coded distance to represent a string that occurs earlier in the
|
|
||||||
* uncompressed data that occurs again at the current location.
|
|
||||||
*
|
|
||||||
* - A bit preceding a literal or length/distance pair indicates which comes
|
|
||||||
* next, 0 for literals, 1 for length/distance.
|
|
||||||
*
|
|
||||||
* - If literals are uncoded, then the next eight bits are the literal, in the
|
|
||||||
* normal bit order in th stream, i.e. no bit-reversal is needed. Similarly,
|
|
||||||
* no bit reversal is needed for either the length extra bits or the distance
|
|
||||||
* extra bits.
|
|
||||||
*
|
|
||||||
* - Literal bytes are simply written to the output. A length/distance pair is
|
|
||||||
* an instruction to copy previously uncompressed bytes to the output. The
|
|
||||||
* copy is from distance bytes back in the output stream, copying for length
|
|
||||||
* bytes.
|
|
||||||
*
|
|
||||||
* - Distances pointing before the beginning of the output data are not
|
|
||||||
* permitted.
|
|
||||||
*
|
|
||||||
* - Overlapped copies, where the length is greater than the distance, are
|
|
||||||
* allowed and common. For example, a distance of one and a length of 518
|
|
||||||
* simply copies the last byte 518 times. A distance of four and a length of
|
|
||||||
* twelve copies the last four bytes three times. A simple forward copy
|
|
||||||
* ignoring whether the length is greater than the distance or not implements
|
|
||||||
* this correctly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static byte[] litlen = new byte[] {
|
static byte[] litlen = new byte[] {
|
||||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
|
11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
|
||||||
10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
|
10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
|
||||||
@@ -133,7 +55,8 @@ namespace OpenRA.FileFormats
|
|||||||
static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
|
static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
|
||||||
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
|
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
|
||||||
static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
|
static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
|
||||||
|
|
||||||
|
// Decode PKWare Compression Library stream.
|
||||||
public static byte[] Decompress(byte[] src)
|
public static byte[] Decompress(byte[] src)
|
||||||
{
|
{
|
||||||
BitReader br = new BitReader(src);
|
BitReader br = new BitReader(src);
|
||||||
@@ -228,6 +151,27 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
return ms.ToArray();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode a code using huffman table h.
|
||||||
|
private static int Decode(Huffman h, BitReader br)
|
||||||
|
{
|
||||||
|
int code = 0; // len bits being decoded
|
||||||
|
int first = 0; // first code of length len
|
||||||
|
int index = 0; // index of first code of length len in symbol table
|
||||||
|
short next = 1;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
code |= br.ReadBits(1) ^ 1; // invert code
|
||||||
|
int count = h.Count[next++];
|
||||||
|
if (code < first + count)
|
||||||
|
return h.Symbol[index + (code - first)];
|
||||||
|
|
||||||
|
index += count;
|
||||||
|
first += count;
|
||||||
|
first <<= 1;
|
||||||
|
code <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitReader
|
class BitReader
|
||||||
|
|||||||
Reference in New Issue
Block a user