You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.3 KiB
262 lines
7.3 KiB
/*
|
|
* Copyright 2012 dorkbox, llc
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package dorkbox.cabParser.decompress.lzx;
|
|
|
|
import dorkbox.cabParser.CorruptCabException;
|
|
|
|
final class DecompressLzxTree implements LZXConstants {
|
|
private int size;
|
|
private int[] aa;
|
|
int[] LENS;
|
|
|
|
private int[] a1;
|
|
private int[] a2;
|
|
private int[] table;
|
|
|
|
private int b1;
|
|
private int b2;
|
|
private int b3;
|
|
private int b4;
|
|
|
|
private DecompressLzx decompressor;
|
|
private DecompressLzxTree root;
|
|
|
|
private int[] c1 = new int[17];
|
|
private int[] c2 = new int[17];
|
|
private int[] c3 = new int[18];
|
|
private static final byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
|
|
|
DecompressLzxTree(int size, int paramInt2, DecompressLzx decompressor, DecompressLzxTree root) {
|
|
this.size = size;
|
|
this.b1 = paramInt2;
|
|
this.decompressor = decompressor;
|
|
this.root = root;
|
|
this.b2 = 1 << this.b1;
|
|
this.b3 = this.b2 - 1;
|
|
this.b4 = 32 - this.b1;
|
|
this.a1 = new int[this.size * 2];
|
|
this.a2 = new int[this.size * 2];
|
|
this.table = new int[this.b2];
|
|
this.aa = new int[this.size];
|
|
this.LENS = new int[this.size];
|
|
}
|
|
|
|
void reset() {
|
|
for (int i = 0; i < this.size; i++) {
|
|
this.LENS[i] = 0;
|
|
this.aa[i] = 0;
|
|
}
|
|
}
|
|
|
|
void readLengths() {
|
|
for (int i = 0; i < this.size; i++) {
|
|
this.LENS[i] = this.decompressor.readBits(3);
|
|
}
|
|
}
|
|
|
|
void readLengths(int first, int last) throws CorruptCabException {
|
|
for(int i = 0;i<20;i++) {
|
|
this.root.LENS[i] = (byte) this.decompressor.readBits(4);
|
|
}
|
|
|
|
this.root.buildTable();
|
|
|
|
for (int i = first; i < last; i++) {
|
|
int k = this.root.decodeElement();
|
|
int j;
|
|
|
|
if (k == 17) {
|
|
j = this.decompressor.readBits(4) + 4;
|
|
if (i + j >= last) {
|
|
j = last - i;
|
|
}
|
|
while (j-- > 0) {
|
|
this.LENS[i++] = 0;
|
|
}
|
|
i--;
|
|
}
|
|
else if (k == 18) {
|
|
j = this.decompressor.readBits(5) + 20;
|
|
if (i + j >= last) {
|
|
j = last - i;
|
|
}
|
|
while (j-- > 0) {
|
|
this.LENS[i++] = 0;
|
|
}
|
|
i--;
|
|
}
|
|
else if (k == 19) {
|
|
j = this.decompressor.readBits(1) + 4;
|
|
if (i + j >= last) {
|
|
j = last - i;
|
|
}
|
|
|
|
k = this.root.decodeElement();
|
|
int m = array[this.aa[i] - k + 17];
|
|
|
|
while (j-- > 0) {
|
|
this.LENS[i++] = m;
|
|
}
|
|
i--;
|
|
}
|
|
else {
|
|
this.LENS[i] = array[this.aa[i] - k + 17];
|
|
}
|
|
}
|
|
}
|
|
|
|
void buildTable() throws CorruptCabException {
|
|
int[] table = this.table;
|
|
int[] c3 = this.c3;
|
|
int b1 = this.b1;
|
|
int i = 1;
|
|
|
|
do {
|
|
this.c1[i] = 0;
|
|
i++;
|
|
} while (i <= 16);
|
|
|
|
for (i = 0; i < this.size; i++) {
|
|
this.c1[this.LENS[i]]++;
|
|
}
|
|
|
|
c3[1] = 0;
|
|
i = 1;
|
|
do {
|
|
c3[i + 1] = c3[i] + (this.c1[i] << 16 - i);
|
|
i++;
|
|
} while (i <= 16);
|
|
if (c3[17] != 65536) {
|
|
if (c3[17] == 0) {
|
|
for (i = 0; i < this.b2; i++) {
|
|
table[i] = 0;
|
|
}
|
|
return;
|
|
}
|
|
throw new CorruptCabException();
|
|
}
|
|
|
|
int i2 = 16 - b1;
|
|
for (i = 1; i <= b1; i++) {
|
|
c3[i] >>>= i2;
|
|
this.c2[i] = 1 << b1 - i;
|
|
}
|
|
|
|
while (i <= 16) {
|
|
this.c2[i] = 1 << 16 - i;
|
|
i++;
|
|
}
|
|
|
|
i = c3[b1 + 1] >>> i2;
|
|
if (i != 65536) {
|
|
while (i < this.b2) {
|
|
table[i] = 0;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
int k = this.size;
|
|
for (int j = 0; j < this.size; j++) {
|
|
int i1 = this.LENS[j];
|
|
if (i1 != 0) {
|
|
int m = c3[i1] + this.c2[i1];
|
|
if (i1 <= b1) {
|
|
if (m > this.b2) {
|
|
throw new CorruptCabException();
|
|
}
|
|
for (i = c3[i1]; i < m; i++) {
|
|
table[i] = j;
|
|
}
|
|
c3[i1] = m;
|
|
} else {
|
|
int n = c3[i1];
|
|
c3[i1] = m;
|
|
int i6 = n >>> i2;
|
|
int i5 = 2;
|
|
i = i1 - b1;
|
|
n <<= b1;
|
|
|
|
do {
|
|
int i4;
|
|
if (i5 == 2) {
|
|
i4 = table[i6];
|
|
}
|
|
else if (i5 == 0) {
|
|
i4 = this.a1[i6];
|
|
}
|
|
else {
|
|
i4 = this.a2[i6];
|
|
}
|
|
|
|
if (i4 == 0) {
|
|
this.a1[k] = 0;
|
|
this.a2[k] = 0;
|
|
if (i5 == 2) {
|
|
table[i6] = -k;
|
|
} else if (i5 == 0) {
|
|
this.a1[i6] = -k;
|
|
} else {
|
|
this.a2[i6] = -k;
|
|
}
|
|
i4 = -k;
|
|
k++;
|
|
}
|
|
|
|
i6 = -i4;
|
|
if ((n & 0x8000) == 0) {
|
|
i5 = 0;
|
|
} else {
|
|
i5 = 1;
|
|
}
|
|
n <<= 1;
|
|
i--;
|
|
} while (i != 0);
|
|
|
|
if (i5 == 0) {
|
|
this.a1[i6] = j;
|
|
} else {
|
|
this.a2[i6] = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void read() {
|
|
System.arraycopy(this.LENS, 0, this.aa, 0, this.size);
|
|
}
|
|
|
|
int decodeElement() {
|
|
int i = this.table[this.decompressor.bitsLeft >>> this.b4 & this.b3];
|
|
|
|
while (i < 0) {
|
|
int j = 1 << this.b4 - 1;
|
|
do {
|
|
i = -i;
|
|
if ((this.decompressor.bitsLeft & j) == 0) {
|
|
i = this.a1[i];
|
|
} else {
|
|
i = this.a2[i];
|
|
}
|
|
j >>>= 1;
|
|
} while (i < 0);
|
|
}
|
|
|
|
this.decompressor.readNumberBits(this.LENS[i]);
|
|
return i;
|
|
}
|
|
}
|