1
// InflaterHuffmanTree.cs
2
// Copyright (C) 2001 Mike Krueger
4
// This file was translated from java, it was part of the GNU Classpath
5
// Copyright (C) 2001 Free Software Foundation, Inc.
7
// This program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public License
9
// as published by the Free Software Foundation; either version 2
10
// of the License, or (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with this program; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
// Linking this library statically or dynamically with other modules is
22
// making a combined work based on this library. Thus, the terms and
23
// conditions of the GNU General Public License cover the whole
26
// As a special exception, the copyright holders of this library give you
27
// permission to link this library with independent modules to produce an
28
// executable, regardless of the license terms of these independent
29
// modules, and to copy and distribute the resulting executable under
30
// terms of your choice, provided that you also meet, for each linked
31
// independent module, the terms and conditions of the license of that
32
// module. An independent module is a module which is not derived from
33
// or based on this library. If you modify this library, you may extend
34
// this exception to your version of the library, but you are not
35
// obligated to do so. If you do not wish to do so, delete this
36
// exception statement from your version.
40
using PdfSharp.SharpZipLib.Zip.Compression.Streams;
42
namespace PdfSharp.SharpZipLib.Zip.Compression
46
/// Huffman tree used for inflation
48
internal class InflaterHuffmanTree
50
static int MAX_BITLEN = 15;
54
/// Literal length tree
56
public static InflaterHuffmanTree defLitLenTree;
61
public static InflaterHuffmanTree defDistTree;
63
static InflaterHuffmanTree()
66
byte[] codeLengths = new byte[288];
80
defLitLenTree = new InflaterHuffmanTree(codeLengths);
82
codeLengths = new byte[32];
87
defDistTree = new InflaterHuffmanTree(codeLengths);
89
throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal");
94
/// Constructs a Huffman tree from the array of code lengths.
96
/// <param name = "codeLengths">
97
/// the array of code lengths
99
public InflaterHuffmanTree(byte[] codeLengths)
101
BuildTree(codeLengths);
104
void BuildTree(byte[] codeLengths)
106
int[] blCount = new int[MAX_BITLEN + 1];
107
int[] nextCode = new int[MAX_BITLEN + 1];
109
for (int i = 0; i < codeLengths.Length; i++) {
110
int bits = codeLengths[i];
118
for (int bits = 1; bits <= MAX_BITLEN; bits++) {
119
nextCode[bits] = code;
120
code += blCount[bits] << (16 - bits);
122
/* We need an extra table for bit lengths >= 10. */
123
int start = nextCode[bits] & 0x1ff80;
124
int end = code & 0x1ff80;
125
treeSize += (end - start) >> (16 - bits);
129
/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g
132
throw new SharpZipBaseException("Code lengths don't add up properly.");
135
/* Now create and fill the extra tables from longest to shortest
136
* bit len. This way the sub trees will be aligned.
138
tree = new short[treeSize];
140
for (int bits = MAX_BITLEN; bits >= 10; bits--) {
141
int end = code & 0x1ff80;
142
code -= blCount[bits] << (16 - bits);
143
int start = code & 0x1ff80;
144
for (int i = start; i < end; i += 1 << 7) {
145
tree[DeflaterHuffman.BitReverse(i)] = (short) ((-treePtr << 4) | bits);
146
treePtr += 1 << (bits-9);
150
for (int i = 0; i < codeLengths.Length; i++) {
151
int bits = codeLengths[i];
155
code = nextCode[bits];
156
int revcode = DeflaterHuffman.BitReverse(code);
159
tree[revcode] = (short) ((i << 4) | bits);
160
revcode += 1 << bits;
161
} while (revcode < 512);
163
int subTree = tree[revcode & 511];
164
int treeLen = 1 << (subTree & 15);
165
subTree = -(subTree >> 4);
167
tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
168
revcode += 1 << bits;
169
} while (revcode < treeLen);
171
nextCode[bits] = code + (1 << (16 - bits));
177
/// Reads the next symbol from input. The symbol is encoded using the
180
/// <param name="input">
181
/// input the input source.
184
/// the next symbol, or -1 if not enough input is available.
186
public int GetSymbol(StreamManipulator input)
188
int lookahead, symbol;
189
if ((lookahead = input.PeekBits(9)) >= 0) {
190
if ((symbol = tree[lookahead]) >= 0) {
191
input.DropBits(symbol & 15);
194
int subtree = -(symbol >> 4);
195
int bitlen = symbol & 15;
196
if ((lookahead = input.PeekBits(bitlen)) >= 0) {
197
symbol = tree[subtree | (lookahead >> 9)];
198
input.DropBits(symbol & 15);
201
int bits = input.AvailableBits;
202
lookahead = input.PeekBits(bits);
203
symbol = tree[subtree | (lookahead >> 9)];
204
if ((symbol & 15) <= bits) {
205
input.DropBits(symbol & 15);
212
int bits = input.AvailableBits;
213
lookahead = input.PeekBits(bits);
214
symbol = tree[lookahead];
215
if (symbol >= 0 && (symbol & 15) <= bits) {
216
input.DropBits(symbol & 15);