mirror of
https://github.com/codedread/bitjs
synced 2025-10-04 18:19:15 +02:00
converting to spaces
This commit is contained in:
parent
b451b46828
commit
f460784a48
3 changed files with 486 additions and 486 deletions
2
io.js
2
io.js
|
@ -15,7 +15,7 @@ bitjs.io = bitjs.io || {};
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
// mask for getting the Nth bit (zero-based)
|
// mask for getting the Nth bit (zero-based)
|
||||||
bitjs.BIT = [ 0x01, 0x02, 0x04, 0x08,
|
bitjs.BIT = [ 0x01, 0x02, 0x04, 0x08,
|
||||||
0x10, 0x20, 0x40, 0x80,
|
0x10, 0x20, 0x40, 0x80,
|
||||||
0x100, 0x200, 0x400, 0x800,
|
0x100, 0x200, 0x400, 0x800,
|
||||||
0x1000, 0x2000, 0x4000, 0x8000];
|
0x1000, 0x2000, 0x4000, 0x8000];
|
||||||
|
|
44
untar.js
44
untar.js
|
@ -61,19 +61,19 @@ var TarLocalFile = function(bstream) {
|
||||||
this.maybeMagic = readCleanString(bstream, 6);
|
this.maybeMagic = readCleanString(bstream, 6);
|
||||||
|
|
||||||
if (this.maybeMagic == "ustar") {
|
if (this.maybeMagic == "ustar") {
|
||||||
this.version = readCleanString(bstream, 2);
|
this.version = readCleanString(bstream, 2);
|
||||||
this.uname = readCleanString(bstream, 32);
|
this.uname = readCleanString(bstream, 32);
|
||||||
this.gname = readCleanString(bstream, 32);
|
this.gname = readCleanString(bstream, 32);
|
||||||
this.devmajor = readCleanString(bstream, 8);
|
this.devmajor = readCleanString(bstream, 8);
|
||||||
this.devminor = readCleanString(bstream, 8);
|
this.devminor = readCleanString(bstream, 8);
|
||||||
this.prefix = readCleanString(bstream, 155);
|
this.prefix = readCleanString(bstream, 155);
|
||||||
|
|
||||||
if (this.prefix.length) {
|
if (this.prefix.length) {
|
||||||
this.name = this.prefix + this.name;
|
this.name = this.prefix + this.name;
|
||||||
}
|
}
|
||||||
bstream.readBytes(12); // 512 - 500
|
bstream.readBytes(12); // 512 - 500
|
||||||
} else {
|
} else {
|
||||||
bstream.readBytes(255); // 512 - 257
|
bstream.readBytes(255); // 512 - 257
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done header, now rest of blocks are the file contents.
|
// Done header, now rest of blocks are the file contents.
|
||||||
|
@ -86,22 +86,22 @@ var TarLocalFile = function(bstream) {
|
||||||
|
|
||||||
// A regular file.
|
// A regular file.
|
||||||
if (this.typeflag == 0) {
|
if (this.typeflag == 0) {
|
||||||
info(" This is a regular file.");
|
info(" This is a regular file.");
|
||||||
var sizeInBytes = parseInt(this.size);
|
var sizeInBytes = parseInt(this.size);
|
||||||
this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
|
this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
|
||||||
if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
|
if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
|
||||||
this.isValid = true;
|
this.isValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bstream.readBytes(this.size);
|
bstream.readBytes(this.size);
|
||||||
|
|
||||||
// Round up to 512-byte blocks.
|
// Round up to 512-byte blocks.
|
||||||
var remaining = 512 - this.size % 512;
|
var remaining = 512 - this.size % 512;
|
||||||
if (remaining > 0 && remaining < 512) {
|
if (remaining > 0 && remaining < 512) {
|
||||||
bstream.readBytes(remaining);
|
bstream.readBytes(remaining);
|
||||||
}
|
}
|
||||||
} else if (this.typeflag == 5) {
|
} else if (this.typeflag == 5) {
|
||||||
info(" This is a directory.")
|
info(" This is a directory.")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,11 +122,11 @@ var untar = function(arrayBuffer) {
|
||||||
|
|
||||||
// While we don't encounter an empty block, keep making TarLocalFiles.
|
// While we don't encounter an empty block, keep making TarLocalFiles.
|
||||||
while (bstream.peekNumber(4) != 0) {
|
while (bstream.peekNumber(4) != 0) {
|
||||||
var oneLocalFile = new TarLocalFile(bstream);
|
var oneLocalFile = new TarLocalFile(bstream);
|
||||||
if (oneLocalFile && oneLocalFile.isValid) {
|
if (oneLocalFile && oneLocalFile.isValid) {
|
||||||
localFiles.push(oneLocalFile);
|
localFiles.push(oneLocalFile);
|
||||||
totalUncompressedBytesInArchive += oneLocalFile.size;
|
totalUncompressedBytesInArchive += oneLocalFile.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalFilesInArchive = localFiles.length;
|
totalFilesInArchive = localFiles.length;
|
||||||
|
|
||||||
|
|
926
unzip.js
926
unzip.js
|
@ -48,62 +48,62 @@ var zEndOfCentralDirLocatorSignature = 0x07064b50;
|
||||||
|
|
||||||
// takes a ByteStream and parses out the local file information
|
// takes a ByteStream and parses out the local file information
|
||||||
var ZipLocalFile = function(bstream) {
|
var ZipLocalFile = function(bstream) {
|
||||||
if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function(){}) {
|
if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function(){}) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bstream.readNumber(4); // swallow signature
|
bstream.readNumber(4); // swallow signature
|
||||||
this.version = bstream.readNumber(2);
|
this.version = bstream.readNumber(2);
|
||||||
this.generalPurpose = bstream.readNumber(2);
|
this.generalPurpose = bstream.readNumber(2);
|
||||||
this.compressionMethod = bstream.readNumber(2);
|
this.compressionMethod = bstream.readNumber(2);
|
||||||
this.lastModFileTime = bstream.readNumber(2);
|
this.lastModFileTime = bstream.readNumber(2);
|
||||||
this.lastModFileDate = bstream.readNumber(2);
|
this.lastModFileDate = bstream.readNumber(2);
|
||||||
this.crc32 = bstream.readNumber(4);
|
this.crc32 = bstream.readNumber(4);
|
||||||
this.compressedSize = bstream.readNumber(4);
|
this.compressedSize = bstream.readNumber(4);
|
||||||
this.uncompressedSize = bstream.readNumber(4);
|
this.uncompressedSize = bstream.readNumber(4);
|
||||||
this.fileNameLength = bstream.readNumber(2);
|
this.fileNameLength = bstream.readNumber(2);
|
||||||
this.extraFieldLength = bstream.readNumber(2);
|
this.extraFieldLength = bstream.readNumber(2);
|
||||||
|
|
||||||
this.filename = null;
|
this.filename = null;
|
||||||
if (this.fileNameLength > 0) {
|
if (this.fileNameLength > 0) {
|
||||||
this.filename = bstream.readString(this.fileNameLength);
|
this.filename = bstream.readString(this.fileNameLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Zip Local File Header:");
|
info("Zip Local File Header:");
|
||||||
info(" version=" + this.version);
|
info(" version=" + this.version);
|
||||||
info(" general purpose=" + this.generalPurpose);
|
info(" general purpose=" + this.generalPurpose);
|
||||||
info(" compression method=" + this.compressionMethod);
|
info(" compression method=" + this.compressionMethod);
|
||||||
info(" last mod file time=" + this.lastModFileTime);
|
info(" last mod file time=" + this.lastModFileTime);
|
||||||
info(" last mod file date=" + this.lastModFileDate);
|
info(" last mod file date=" + this.lastModFileDate);
|
||||||
info(" crc32=" + this.crc32);
|
info(" crc32=" + this.crc32);
|
||||||
info(" compressed size=" + this.compressedSize);
|
info(" compressed size=" + this.compressedSize);
|
||||||
info(" uncompressed size=" + this.uncompressedSize);
|
info(" uncompressed size=" + this.uncompressedSize);
|
||||||
info(" file name length=" + this.fileNameLength);
|
info(" file name length=" + this.fileNameLength);
|
||||||
info(" extra field length=" + this.extraFieldLength);
|
info(" extra field length=" + this.extraFieldLength);
|
||||||
info(" filename = '" + this.filename + "'");
|
info(" filename = '" + this.filename + "'");
|
||||||
|
|
||||||
this.extraField = null;
|
this.extraField = null;
|
||||||
if (this.extraFieldLength > 0) {
|
if (this.extraFieldLength > 0) {
|
||||||
this.extraField = bstream.readString(this.extraFieldLength);
|
this.extraField = bstream.readString(this.extraFieldLength);
|
||||||
info(" extra field=" + this.extraField);
|
info(" extra field=" + this.extraField);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read in the compressed data
|
// read in the compressed data
|
||||||
this.fileData = null;
|
this.fileData = null;
|
||||||
if (this.compressedSize > 0) {
|
if (this.compressedSize > 0) {
|
||||||
this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.compressedSize);
|
this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.compressedSize);
|
||||||
bstream.ptr += this.compressedSize;
|
bstream.ptr += this.compressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: deal with data descriptor if present (we currently assume no data descriptor!)
|
// TODO: deal with data descriptor if present (we currently assume no data descriptor!)
|
||||||
// "This descriptor exists only if bit 3 of the general purpose bit flag is set"
|
// "This descriptor exists only if bit 3 of the general purpose bit flag is set"
|
||||||
// But how do you figure out how big the file data is if you don't know the compressedSize
|
// But how do you figure out how big the file data is if you don't know the compressedSize
|
||||||
// from the header?!?
|
// from the header?!?
|
||||||
if ((this.generalPurpose & bitjs.BIT[3]) != 0) {
|
if ((this.generalPurpose & bitjs.BIT[3]) != 0) {
|
||||||
this.crc32 = bstream.readNumber(4);
|
this.crc32 = bstream.readNumber(4);
|
||||||
this.compressedSize = bstream.readNumber(4);
|
this.compressedSize = bstream.readNumber(4);
|
||||||
this.uncompressedSize = bstream.readNumber(4);
|
this.uncompressedSize = bstream.readNumber(4);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// determine what kind of compressed data we have and decompress
|
// determine what kind of compressed data we have and decompress
|
||||||
|
@ -144,119 +144,119 @@ var unzip = function(arrayBuffer) {
|
||||||
var bstream = new bitjs.io.ByteStream(arrayBuffer);
|
var bstream = new bitjs.io.ByteStream(arrayBuffer);
|
||||||
// detect local file header signature or return null
|
// detect local file header signature or return null
|
||||||
if (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
|
if (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
|
||||||
var localFiles = [];
|
var localFiles = [];
|
||||||
// loop until we don't see any more local files
|
// loop until we don't see any more local files
|
||||||
while (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
|
while (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
|
||||||
var oneLocalFile = new ZipLocalFile(bstream);
|
var oneLocalFile = new ZipLocalFile(bstream);
|
||||||
// this should strip out directories/folders
|
// this should strip out directories/folders
|
||||||
if (oneLocalFile && oneLocalFile.uncompressedSize > 0 && oneLocalFile.fileData) {
|
if (oneLocalFile && oneLocalFile.uncompressedSize > 0 && oneLocalFile.fileData) {
|
||||||
localFiles.push(oneLocalFile);
|
localFiles.push(oneLocalFile);
|
||||||
totalUncompressedBytesInArchive += oneLocalFile.uncompressedSize;
|
totalUncompressedBytesInArchive += oneLocalFile.uncompressedSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalFilesInArchive = localFiles.length;
|
totalFilesInArchive = localFiles.length;
|
||||||
|
|
||||||
// got all local files, now sort them
|
// got all local files, now sort them
|
||||||
localFiles.sort(function(a,b) {
|
localFiles.sort(function(a,b) {
|
||||||
var aname = a.filename;
|
var aname = a.filename;
|
||||||
var bname = b.filename;
|
var bname = b.filename;
|
||||||
return aname > bname ? 1 : -1;
|
return aname > bname ? 1 : -1;
|
||||||
|
|
||||||
// extract the number at the end of both filenames
|
// extract the number at the end of both filenames
|
||||||
/*
|
/*
|
||||||
var aname = a.filename;
|
var aname = a.filename;
|
||||||
var bname = b.filename;
|
var bname = b.filename;
|
||||||
var aindex = aname.length, bindex = bname.length;
|
var aindex = aname.length, bindex = bname.length;
|
||||||
|
|
||||||
// Find the last number character from the back of the filename.
|
// Find the last number character from the back of the filename.
|
||||||
while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex;
|
while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex;
|
||||||
while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex;
|
while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex;
|
||||||
|
|
||||||
// Find the first number character from the back of the filename
|
// Find the first number character from the back of the filename
|
||||||
while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex;
|
while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex;
|
||||||
while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex;
|
while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex;
|
||||||
|
|
||||||
// parse them into numbers and return comparison
|
// parse them into numbers and return comparison
|
||||||
var anum = parseInt(aname.substr(aindex), 10),
|
var anum = parseInt(aname.substr(aindex), 10),
|
||||||
bnum = parseInt(bname.substr(bindex), 10);
|
bnum = parseInt(bname.substr(bindex), 10);
|
||||||
return anum - bnum;
|
return anum - bnum;
|
||||||
*/
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
// archive extra data record
|
// archive extra data record
|
||||||
if (bstream.peekNumber(4) == zArchiveExtraDataSignature) {
|
if (bstream.peekNumber(4) == zArchiveExtraDataSignature) {
|
||||||
info(" Found an Archive Extra Data Signature");
|
info(" Found an Archive Extra Data Signature");
|
||||||
|
|
||||||
// skipping this record for now
|
// skipping this record for now
|
||||||
bstream.readNumber(4);
|
bstream.readNumber(4);
|
||||||
var archiveExtraFieldLength = bstream.readNumber(4);
|
var archiveExtraFieldLength = bstream.readNumber(4);
|
||||||
bstream.readString(archiveExtraFieldLength);
|
bstream.readString(archiveExtraFieldLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// central directory structure
|
// central directory structure
|
||||||
// TODO: handle the rest of the structures (Zip64 stuff)
|
// TODO: handle the rest of the structures (Zip64 stuff)
|
||||||
if (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
|
if (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
|
||||||
info(" Found a Central File Header");
|
info(" Found a Central File Header");
|
||||||
|
|
||||||
// read all file headers
|
// read all file headers
|
||||||
while (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
|
while (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
|
||||||
bstream.readNumber(4); // signature
|
bstream.readNumber(4); // signature
|
||||||
bstream.readNumber(2); // version made by
|
bstream.readNumber(2); // version made by
|
||||||
bstream.readNumber(2); // version needed to extract
|
bstream.readNumber(2); // version needed to extract
|
||||||
bstream.readNumber(2); // general purpose bit flag
|
bstream.readNumber(2); // general purpose bit flag
|
||||||
bstream.readNumber(2); // compression method
|
bstream.readNumber(2); // compression method
|
||||||
bstream.readNumber(2); // last mod file time
|
bstream.readNumber(2); // last mod file time
|
||||||
bstream.readNumber(2); // last mod file date
|
bstream.readNumber(2); // last mod file date
|
||||||
bstream.readNumber(4); // crc32
|
bstream.readNumber(4); // crc32
|
||||||
bstream.readNumber(4); // compressed size
|
bstream.readNumber(4); // compressed size
|
||||||
bstream.readNumber(4); // uncompressed size
|
bstream.readNumber(4); // uncompressed size
|
||||||
var fileNameLength = bstream.readNumber(2); // file name length
|
var fileNameLength = bstream.readNumber(2); // file name length
|
||||||
var extraFieldLength = bstream.readNumber(2); // extra field length
|
var extraFieldLength = bstream.readNumber(2); // extra field length
|
||||||
var fileCommentLength = bstream.readNumber(2); // file comment length
|
var fileCommentLength = bstream.readNumber(2); // file comment length
|
||||||
bstream.readNumber(2); // disk number start
|
bstream.readNumber(2); // disk number start
|
||||||
bstream.readNumber(2); // internal file attributes
|
bstream.readNumber(2); // internal file attributes
|
||||||
bstream.readNumber(4); // external file attributes
|
bstream.readNumber(4); // external file attributes
|
||||||
bstream.readNumber(4); // relative offset of local header
|
bstream.readNumber(4); // relative offset of local header
|
||||||
|
|
||||||
bstream.readString(fileNameLength); // file name
|
bstream.readString(fileNameLength); // file name
|
||||||
bstream.readString(extraFieldLength); // extra field
|
bstream.readString(extraFieldLength); // extra field
|
||||||
bstream.readString(fileCommentLength); // file comment
|
bstream.readString(fileCommentLength); // file comment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// digital signature
|
// digital signature
|
||||||
if (bstream.peekNumber(4) == zDigitalSignatureSignature) {
|
if (bstream.peekNumber(4) == zDigitalSignatureSignature) {
|
||||||
info(" Found a Digital Signature");
|
info(" Found a Digital Signature");
|
||||||
|
|
||||||
bstream.readNumber(4);
|
bstream.readNumber(4);
|
||||||
var sizeOfSignature = bstream.readNumber(2);
|
var sizeOfSignature = bstream.readNumber(2);
|
||||||
bstream.readString(sizeOfSignature); // digital signature data
|
bstream.readString(sizeOfSignature); // digital signature data
|
||||||
}
|
}
|
||||||
|
|
||||||
// report # files and total length
|
// report # files and total length
|
||||||
if (localFiles.length > 0) {
|
if (localFiles.length > 0) {
|
||||||
postProgress();
|
postProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// now do the unzipping of each file
|
// now do the unzipping of each file
|
||||||
for (var i = 0; i < localFiles.length; ++i) {
|
for (var i = 0; i < localFiles.length; ++i) {
|
||||||
var localfile = localFiles[i];
|
var localfile = localFiles[i];
|
||||||
|
|
||||||
// update progress
|
// update progress
|
||||||
currentFilename = localfile.filename;
|
currentFilename = localfile.filename;
|
||||||
currentFileNumber = i;
|
currentFileNumber = i;
|
||||||
currentBytesUnarchivedInFile = 0;
|
currentBytesUnarchivedInFile = 0;
|
||||||
|
|
||||||
// actually do the unzipping
|
// actually do the unzipping
|
||||||
localfile.unzip();
|
localfile.unzip();
|
||||||
|
|
||||||
if (localfile.fileData != null) {
|
if (localfile.fileData != null) {
|
||||||
postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile));
|
postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile));
|
||||||
postProgress();
|
postProgress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postProgress();
|
postProgress();
|
||||||
postMessage(new bitjs.archive.UnarchiveFinishEvent());
|
postMessage(new bitjs.archive.UnarchiveFinishEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,253 +264,253 @@ var unzip = function(arrayBuffer) {
|
||||||
// each entry's index is its code and its value is a JavaScript object
|
// each entry's index is its code and its value is a JavaScript object
|
||||||
// containing {length: 6, symbol: X}
|
// containing {length: 6, symbol: X}
|
||||||
function getHuffmanCodes(bitLengths) {
|
function getHuffmanCodes(bitLengths) {
|
||||||
// ensure bitLengths is an array containing at least one element
|
// ensure bitLengths is an array containing at least one element
|
||||||
if (typeof bitLengths != typeof [] || bitLengths.length < 1) {
|
if (typeof bitLengths != typeof [] || bitLengths.length < 1) {
|
||||||
err("Error! getHuffmanCodes() called with an invalid array");
|
err("Error! getHuffmanCodes() called with an invalid array");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference: http://tools.ietf.org/html/rfc1951#page-8
|
// Reference: http://tools.ietf.org/html/rfc1951#page-8
|
||||||
var numLengths = bitLengths.length,
|
var numLengths = bitLengths.length,
|
||||||
bl_count = [],
|
bl_count = [],
|
||||||
MAX_BITS = 1;
|
MAX_BITS = 1;
|
||||||
|
|
||||||
// Step 1: count up how many codes of each length we have
|
// Step 1: count up how many codes of each length we have
|
||||||
for (var i = 0; i < numLengths; ++i) {
|
for (var i = 0; i < numLengths; ++i) {
|
||||||
var length = bitLengths[i];
|
var length = bitLengths[i];
|
||||||
// test to ensure each bit length is a positive, non-zero number
|
// test to ensure each bit length is a positive, non-zero number
|
||||||
if (typeof length != typeof 1 || length < 0) {
|
if (typeof length != typeof 1 || length < 0) {
|
||||||
err("bitLengths contained an invalid number in getHuffmanCodes(): " + length + " of type " + (typeof length));
|
err("bitLengths contained an invalid number in getHuffmanCodes(): " + length + " of type " + (typeof length));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// increment the appropriate bitlength count
|
// increment the appropriate bitlength count
|
||||||
if (bl_count[length] == undefined) bl_count[length] = 0;
|
if (bl_count[length] == undefined) bl_count[length] = 0;
|
||||||
// a length of zero means this symbol is not participating in the huffman coding
|
// a length of zero means this symbol is not participating in the huffman coding
|
||||||
if (length > 0) bl_count[length]++;
|
if (length > 0) bl_count[length]++;
|
||||||
|
|
||||||
if (length > MAX_BITS) MAX_BITS = length;
|
if (length > MAX_BITS) MAX_BITS = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Find the numerical value of the smallest code for each code length
|
// Step 2: Find the numerical value of the smallest code for each code length
|
||||||
var next_code = [],
|
var next_code = [],
|
||||||
code = 0;
|
code = 0;
|
||||||
for (var bits = 1; bits <= MAX_BITS; ++bits) {
|
for (var bits = 1; bits <= MAX_BITS; ++bits) {
|
||||||
var length = bits-1;
|
var length = bits-1;
|
||||||
// ensure undefined lengths are zero
|
// ensure undefined lengths are zero
|
||||||
if (bl_count[length] == undefined) bl_count[length] = 0;
|
if (bl_count[length] == undefined) bl_count[length] = 0;
|
||||||
code = (code + bl_count[bits-1]) << 1;
|
code = (code + bl_count[bits-1]) << 1;
|
||||||
next_code[bits] = code;
|
next_code[bits] = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Assign numerical values to all codes
|
// Step 3: Assign numerical values to all codes
|
||||||
var table = {}, tableLength = 0;
|
var table = {}, tableLength = 0;
|
||||||
for (var n = 0; n < numLengths; ++n) {
|
for (var n = 0; n < numLengths; ++n) {
|
||||||
var len = bitLengths[n];
|
var len = bitLengths[n];
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
table[next_code[len]] = { length: len, symbol: n }; //, bitstring: binaryValueToString(next_code[len],len) };
|
table[next_code[len]] = { length: len, symbol: n }; //, bitstring: binaryValueToString(next_code[len],len) };
|
||||||
tableLength++;
|
tableLength++;
|
||||||
next_code[len]++;
|
next_code[len]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table.maxLength = tableLength;
|
table.maxLength = tableLength;
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Huffman codes for the two alphabets are fixed, and are not
|
The Huffman codes for the two alphabets are fixed, and are not
|
||||||
represented explicitly in the data. The Huffman code lengths
|
represented explicitly in the data. The Huffman code lengths
|
||||||
for the literal/length alphabet are:
|
for the literal/length alphabet are:
|
||||||
|
|
||||||
Lit Value Bits Codes
|
Lit Value Bits Codes
|
||||||
--------- ---- -----
|
--------- ---- -----
|
||||||
0 - 143 8 00110000 through
|
0 - 143 8 00110000 through
|
||||||
10111111
|
10111111
|
||||||
144 - 255 9 110010000 through
|
144 - 255 9 110010000 through
|
||||||
111111111
|
111111111
|
||||||
256 - 279 7 0000000 through
|
256 - 279 7 0000000 through
|
||||||
0010111
|
0010111
|
||||||
280 - 287 8 11000000 through
|
280 - 287 8 11000000 through
|
||||||
11000111
|
11000111
|
||||||
*/
|
*/
|
||||||
// fixed Huffman codes go from 7-9 bits, so we need an array whose index can hold up to 9 bits
|
// fixed Huffman codes go from 7-9 bits, so we need an array whose index can hold up to 9 bits
|
||||||
var fixedHCtoLiteral = null;
|
var fixedHCtoLiteral = null;
|
||||||
var fixedHCtoDistance = null;
|
var fixedHCtoDistance = null;
|
||||||
function getFixedLiteralTable() {
|
function getFixedLiteralTable() {
|
||||||
// create once
|
// create once
|
||||||
if (!fixedHCtoLiteral) {
|
if (!fixedHCtoLiteral) {
|
||||||
var bitlengths = new Array(288);
|
var bitlengths = new Array(288);
|
||||||
for (var i = 0; i <= 143; ++i) bitlengths[i] = 8;
|
for (var i = 0; i <= 143; ++i) bitlengths[i] = 8;
|
||||||
for (i = 144; i <= 255; ++i) bitlengths[i] = 9;
|
for (i = 144; i <= 255; ++i) bitlengths[i] = 9;
|
||||||
for (i = 256; i <= 279; ++i) bitlengths[i] = 7;
|
for (i = 256; i <= 279; ++i) bitlengths[i] = 7;
|
||||||
for (i = 280; i <= 287; ++i) bitlengths[i] = 8;
|
for (i = 280; i <= 287; ++i) bitlengths[i] = 8;
|
||||||
|
|
||||||
// get huffman code table
|
// get huffman code table
|
||||||
fixedHCtoLiteral = getHuffmanCodes(bitlengths);
|
fixedHCtoLiteral = getHuffmanCodes(bitlengths);
|
||||||
}
|
}
|
||||||
return fixedHCtoLiteral;
|
return fixedHCtoLiteral;
|
||||||
}
|
}
|
||||||
function getFixedDistanceTable() {
|
function getFixedDistanceTable() {
|
||||||
// create once
|
// create once
|
||||||
if (!fixedHCtoDistance) {
|
if (!fixedHCtoDistance) {
|
||||||
var bitlengths = new Array(32);
|
var bitlengths = new Array(32);
|
||||||
for (var i = 0; i < 32; ++i) { bitlengths[i] = 5; }
|
for (var i = 0; i < 32; ++i) { bitlengths[i] = 5; }
|
||||||
|
|
||||||
// get huffman code table
|
// get huffman code table
|
||||||
fixedHCtoDistance = getHuffmanCodes(bitlengths);
|
fixedHCtoDistance = getHuffmanCodes(bitlengths);
|
||||||
}
|
}
|
||||||
return fixedHCtoDistance;
|
return fixedHCtoDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract one bit at a time until we find a matching Huffman Code
|
// extract one bit at a time until we find a matching Huffman Code
|
||||||
// then return that symbol
|
// then return that symbol
|
||||||
function decodeSymbol(bstream, hcTable) {
|
function decodeSymbol(bstream, hcTable) {
|
||||||
var code = 0, len = 0;
|
var code = 0, len = 0;
|
||||||
var match = false;
|
var match = false;
|
||||||
|
|
||||||
// loop until we match
|
// loop until we match
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// read in next bit
|
// read in next bit
|
||||||
var bit = bstream.readBits(1);
|
var bit = bstream.readBits(1);
|
||||||
code = (code<<1) | bit;
|
code = (code<<1) | bit;
|
||||||
++len;
|
++len;
|
||||||
|
|
||||||
// check against Huffman Code table and break if found
|
// check against Huffman Code table and break if found
|
||||||
if (hcTable.hasOwnProperty(code) && hcTable[code].length == len) {
|
if (hcTable.hasOwnProperty(code) && hcTable[code].length == len) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len > hcTable.maxLength) {
|
if (len > hcTable.maxLength) {
|
||||||
err("Bit stream out of sync, didn't find a Huffman Code, length was " + len +
|
err("Bit stream out of sync, didn't find a Huffman Code, length was " + len +
|
||||||
" and table only max code length of " + hcTable.maxLength);
|
" and table only max code length of " + hcTable.maxLength);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hcTable[code].symbol;
|
return hcTable[code].symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var CodeLengthCodeOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
|
var CodeLengthCodeOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
|
||||||
/*
|
/*
|
||||||
Extra Extra Extra
|
Extra Extra Extra
|
||||||
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
||||||
---- ---- ------ ---- ---- ------- ---- ---- -------
|
---- ---- ------ ---- ---- ------- ---- ---- -------
|
||||||
257 0 3 267 1 15,16 277 4 67-82
|
257 0 3 267 1 15,16 277 4 67-82
|
||||||
258 0 4 268 1 17,18 278 4 83-98
|
258 0 4 268 1 17,18 278 4 83-98
|
||||||
259 0 5 269 2 19-22 279 4 99-114
|
259 0 5 269 2 19-22 279 4 99-114
|
||||||
260 0 6 270 2 23-26 280 4 115-130
|
260 0 6 270 2 23-26 280 4 115-130
|
||||||
261 0 7 271 2 27-30 281 5 131-162
|
261 0 7 271 2 27-30 281 5 131-162
|
||||||
262 0 8 272 2 31-34 282 5 163-194
|
262 0 8 272 2 31-34 282 5 163-194
|
||||||
263 0 9 273 3 35-42 283 5 195-226
|
263 0 9 273 3 35-42 283 5 195-226
|
||||||
264 0 10 274 3 43-50 284 5 227-257
|
264 0 10 274 3 43-50 284 5 227-257
|
||||||
265 1 11,12 275 3 51-58 285 0 258
|
265 1 11,12 275 3 51-58 285 0 258
|
||||||
266 1 13,14 276 3 59-66
|
266 1 13,14 276 3 59-66
|
||||||
|
|
||||||
*/
|
*/
|
||||||
var LengthLookupTable = [
|
var LengthLookupTable = [
|
||||||
[0,3], [0,4], [0,5], [0,6],
|
[0,3], [0,4], [0,5], [0,6],
|
||||||
[0,7], [0,8], [0,9], [0,10],
|
[0,7], [0,8], [0,9], [0,10],
|
||||||
[1,11], [1,13], [1,15], [1,17],
|
[1,11], [1,13], [1,15], [1,17],
|
||||||
[2,19], [2,23], [2,27], [2,31],
|
[2,19], [2,23], [2,27], [2,31],
|
||||||
[3,35], [3,43], [3,51], [3,59],
|
[3,35], [3,43], [3,51], [3,59],
|
||||||
[4,67], [4,83], [4,99], [4,115],
|
[4,67], [4,83], [4,99], [4,115],
|
||||||
[5,131], [5,163], [5,195], [5,227],
|
[5,131], [5,163], [5,195], [5,227],
|
||||||
[0,258]
|
[0,258]
|
||||||
];
|
];
|
||||||
/*
|
/*
|
||||||
Extra Extra Extra
|
Extra Extra Extra
|
||||||
Code Bits Dist Code Bits Dist Code Bits Distance
|
Code Bits Dist Code Bits Dist Code Bits Distance
|
||||||
---- ---- ---- ---- ---- ------ ---- ---- --------
|
---- ---- ---- ---- ---- ------ ---- ---- --------
|
||||||
0 0 1 10 4 33-48 20 9 1025-1536
|
0 0 1 10 4 33-48 20 9 1025-1536
|
||||||
1 0 2 11 4 49-64 21 9 1537-2048
|
1 0 2 11 4 49-64 21 9 1537-2048
|
||||||
2 0 3 12 5 65-96 22 10 2049-3072
|
2 0 3 12 5 65-96 22 10 2049-3072
|
||||||
3 0 4 13 5 97-128 23 10 3073-4096
|
3 0 4 13 5 97-128 23 10 3073-4096
|
||||||
4 1 5,6 14 6 129-192 24 11 4097-6144
|
4 1 5,6 14 6 129-192 24 11 4097-6144
|
||||||
5 1 7,8 15 6 193-256 25 11 6145-8192
|
5 1 7,8 15 6 193-256 25 11 6145-8192
|
||||||
6 2 9-12 16 7 257-384 26 12 8193-12288
|
6 2 9-12 16 7 257-384 26 12 8193-12288
|
||||||
7 2 13-16 17 7 385-512 27 12 12289-16384
|
7 2 13-16 17 7 385-512 27 12 12289-16384
|
||||||
8 3 17-24 18 8 513-768 28 13 16385-24576
|
8 3 17-24 18 8 513-768 28 13 16385-24576
|
||||||
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
||||||
*/
|
*/
|
||||||
var DistLookupTable = [
|
var DistLookupTable = [
|
||||||
[0,1], [0,2], [0,3], [0,4],
|
[0,1], [0,2], [0,3], [0,4],
|
||||||
[1,5], [1,7],
|
[1,5], [1,7],
|
||||||
[2,9], [2,13],
|
[2,9], [2,13],
|
||||||
[3,17], [3,25],
|
[3,17], [3,25],
|
||||||
[4,33], [4,49],
|
[4,33], [4,49],
|
||||||
[5,65], [5,97],
|
[5,65], [5,97],
|
||||||
[6,129], [6,193],
|
[6,129], [6,193],
|
||||||
[7,257], [7,385],
|
[7,257], [7,385],
|
||||||
[8,513], [8,769],
|
[8,513], [8,769],
|
||||||
[9,1025], [9,1537],
|
[9,1025], [9,1537],
|
||||||
[10,2049], [10,3073],
|
[10,2049], [10,3073],
|
||||||
[11,4097], [11,6145],
|
[11,4097], [11,6145],
|
||||||
[12,8193], [12,12289],
|
[12,8193], [12,12289],
|
||||||
[13,16385], [13,24577]
|
[13,16385], [13,24577]
|
||||||
];
|
];
|
||||||
|
|
||||||
function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
||||||
/*
|
/*
|
||||||
loop (until end of block code recognized)
|
loop (until end of block code recognized)
|
||||||
decode literal/length value from input stream
|
decode literal/length value from input stream
|
||||||
if value < 256
|
if value < 256
|
||||||
copy value (literal byte) to output stream
|
copy value (literal byte) to output stream
|
||||||
otherwise
|
otherwise
|
||||||
if value = end of block (256)
|
if value = end of block (256)
|
||||||
break from loop
|
break from loop
|
||||||
otherwise (value = 257..285)
|
otherwise (value = 257..285)
|
||||||
decode distance from input stream
|
decode distance from input stream
|
||||||
|
|
||||||
move backwards distance bytes in the output
|
move backwards distance bytes in the output
|
||||||
stream, and copy length bytes from this
|
stream, and copy length bytes from this
|
||||||
position to the output stream.
|
position to the output stream.
|
||||||
*/
|
*/
|
||||||
var numSymbols = 0, blockSize = 0;
|
var numSymbols = 0, blockSize = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
var symbol = decodeSymbol(bstream, hcLiteralTable);
|
var symbol = decodeSymbol(bstream, hcLiteralTable);
|
||||||
++numSymbols;
|
++numSymbols;
|
||||||
if (symbol < 256) {
|
if (symbol < 256) {
|
||||||
// copy literal byte to output
|
// copy literal byte to output
|
||||||
buffer.insertByte(symbol);
|
buffer.insertByte(symbol);
|
||||||
blockSize++;
|
blockSize++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// end of block reached
|
// end of block reached
|
||||||
if (symbol == 256) {
|
if (symbol == 256) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var lengthLookup = LengthLookupTable[symbol-257],
|
var lengthLookup = LengthLookupTable[symbol-257],
|
||||||
length = lengthLookup[1] + bstream.readBits(lengthLookup[0]),
|
length = lengthLookup[1] + bstream.readBits(lengthLookup[0]),
|
||||||
distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)],
|
distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)],
|
||||||
distance = distLookup[1] + bstream.readBits(distLookup[0]);
|
distance = distLookup[1] + bstream.readBits(distLookup[0]);
|
||||||
|
|
||||||
// now apply length and distance appropriately and copy to output
|
// now apply length and distance appropriately and copy to output
|
||||||
|
|
||||||
// TODO: check that backward distance < data.length?
|
// TODO: check that backward distance < data.length?
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc1951#page-11
|
// http://tools.ietf.org/html/rfc1951#page-11
|
||||||
// "Note also that the referenced string may overlap the current
|
// "Note also that the referenced string may overlap the current
|
||||||
// position; for example, if the last 2 bytes decoded have values
|
// position; for example, if the last 2 bytes decoded have values
|
||||||
// X and Y, a string reference with <length = 5, distance = 2>
|
// X and Y, a string reference with <length = 5, distance = 2>
|
||||||
// adds X,Y,X,Y,X to the output stream."
|
// adds X,Y,X,Y,X to the output stream."
|
||||||
//
|
//
|
||||||
// loop for each character
|
// loop for each character
|
||||||
var ch = buffer.ptr - distance;
|
var ch = buffer.ptr - distance;
|
||||||
blockSize += length;
|
blockSize += length;
|
||||||
if(length > distance) {
|
if(length > distance) {
|
||||||
var data = buffer.data;
|
var data = buffer.data;
|
||||||
while (length--) {
|
while (length--) {
|
||||||
buffer.insertByte(data[ch++]);
|
buffer.insertByte(data[ch++]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer.insertBytes(buffer.data.subarray(ch, ch + length))
|
buffer.insertBytes(buffer.data.subarray(ch, ch + length))
|
||||||
}
|
}
|
||||||
|
|
||||||
} // length-distance pair
|
} // length-distance pair
|
||||||
} // length-distance pair or end-of-block
|
} // length-distance pair or end-of-block
|
||||||
} // loop until we reach end of block
|
} // loop until we reach end of block
|
||||||
return blockSize;
|
return blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// {Uint8Array} compressedData A Uint8Array of the compressed file data.
|
// {Uint8Array} compressedData A Uint8Array of the compressed file data.
|
||||||
|
@ -527,42 +527,42 @@ function inflate(compressedData, numDecompressedBytes) {
|
||||||
|
|
||||||
// block format: http://tools.ietf.org/html/rfc1951#page-9
|
// block format: http://tools.ietf.org/html/rfc1951#page-9
|
||||||
do {
|
do {
|
||||||
var bFinal = bstream.readBits(1),
|
var bFinal = bstream.readBits(1),
|
||||||
bType = bstream.readBits(2);
|
bType = bstream.readBits(2);
|
||||||
blockSize = 0;
|
blockSize = 0;
|
||||||
++numBlocks;
|
++numBlocks;
|
||||||
// no compression
|
// no compression
|
||||||
if (bType == 0) {
|
if (bType == 0) {
|
||||||
// skip remaining bits in this byte
|
// skip remaining bits in this byte
|
||||||
while (bstream.bitPtr != 0) bstream.readBits(1);
|
while (bstream.bitPtr != 0) bstream.readBits(1);
|
||||||
var len = bstream.readBits(16),
|
var len = bstream.readBits(16),
|
||||||
nlen = bstream.readBits(16);
|
nlen = bstream.readBits(16);
|
||||||
// TODO: check if nlen is the ones-complement of len?
|
// TODO: check if nlen is the ones-complement of len?
|
||||||
|
|
||||||
if(len > 0) buffer.insertBytes(bstream.readBytes(len));
|
if(len > 0) buffer.insertBytes(bstream.readBytes(len));
|
||||||
blockSize = len;
|
blockSize = len;
|
||||||
}
|
}
|
||||||
// fixed Huffman codes
|
// fixed Huffman codes
|
||||||
else if(bType == 1) {
|
else if(bType == 1) {
|
||||||
blockSize = inflateBlockData(bstream, getFixedLiteralTable(), getFixedDistanceTable(), buffer);
|
blockSize = inflateBlockData(bstream, getFixedLiteralTable(), getFixedDistanceTable(), buffer);
|
||||||
}
|
}
|
||||||
// dynamic Huffman codes
|
// dynamic Huffman codes
|
||||||
else if(bType == 2) {
|
else if(bType == 2) {
|
||||||
var numLiteralLengthCodes = bstream.readBits(5) + 257;
|
var numLiteralLengthCodes = bstream.readBits(5) + 257;
|
||||||
var numDistanceCodes = bstream.readBits(5) + 1,
|
var numDistanceCodes = bstream.readBits(5) + 1,
|
||||||
numCodeLengthCodes = bstream.readBits(4) + 4;
|
numCodeLengthCodes = bstream.readBits(4) + 4;
|
||||||
|
|
||||||
// populate the array of code length codes (first de-compaction)
|
// populate the array of code length codes (first de-compaction)
|
||||||
var codeLengthsCodeLengths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
var codeLengthsCodeLengths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
||||||
for (var i = 0; i < numCodeLengthCodes; ++i) {
|
for (var i = 0; i < numCodeLengthCodes; ++i) {
|
||||||
codeLengthsCodeLengths[ CodeLengthCodeOrder[i] ] = bstream.readBits(3);
|
codeLengthsCodeLengths[ CodeLengthCodeOrder[i] ] = bstream.readBits(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the Huffman Codes for the code lengths
|
// get the Huffman Codes for the code lengths
|
||||||
var codeLengthsCodes = getHuffmanCodes(codeLengthsCodeLengths);
|
var codeLengthsCodes = getHuffmanCodes(codeLengthsCodeLengths);
|
||||||
|
|
||||||
// now follow this mapping
|
// now follow this mapping
|
||||||
/*
|
/*
|
||||||
0 - 15: Represent code lengths of 0 - 15
|
0 - 15: Represent code lengths of 0 - 15
|
||||||
16: Copy the previous code length 3 - 6 times.
|
16: Copy the previous code length 3 - 6 times.
|
||||||
The next 2 bits indicate repeat length
|
The next 2 bits indicate repeat length
|
||||||
|
@ -574,59 +574,59 @@ function inflate(compressedData, numDecompressedBytes) {
|
||||||
(3 bits of length)
|
(3 bits of length)
|
||||||
18: Repeat a code length of 0 for 11 - 138 times
|
18: Repeat a code length of 0 for 11 - 138 times
|
||||||
(7 bits of length)
|
(7 bits of length)
|
||||||
*/
|
*/
|
||||||
// to generate the true code lengths of the Huffman Codes for the literal
|
// to generate the true code lengths of the Huffman Codes for the literal
|
||||||
// and distance tables together
|
// and distance tables together
|
||||||
var literalCodeLengths = [];
|
var literalCodeLengths = [];
|
||||||
var prevCodeLength = 0;
|
var prevCodeLength = 0;
|
||||||
while (literalCodeLengths.length < numLiteralLengthCodes + numDistanceCodes) {
|
while (literalCodeLengths.length < numLiteralLengthCodes + numDistanceCodes) {
|
||||||
var symbol = decodeSymbol(bstream, codeLengthsCodes);
|
var symbol = decodeSymbol(bstream, codeLengthsCodes);
|
||||||
if (symbol <= 15) {
|
if (symbol <= 15) {
|
||||||
literalCodeLengths.push(symbol);
|
literalCodeLengths.push(symbol);
|
||||||
prevCodeLength = symbol;
|
prevCodeLength = symbol;
|
||||||
}
|
}
|
||||||
else if (symbol == 16) {
|
else if (symbol == 16) {
|
||||||
var repeat = bstream.readBits(2) + 3;
|
var repeat = bstream.readBits(2) + 3;
|
||||||
while (repeat--) {
|
while (repeat--) {
|
||||||
literalCodeLengths.push(prevCodeLength);
|
literalCodeLengths.push(prevCodeLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (symbol == 17) {
|
else if (symbol == 17) {
|
||||||
var repeat = bstream.readBits(3) + 3;
|
var repeat = bstream.readBits(3) + 3;
|
||||||
while (repeat--) {
|
while (repeat--) {
|
||||||
literalCodeLengths.push(0);
|
literalCodeLengths.push(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (symbol == 18) {
|
else if (symbol == 18) {
|
||||||
var repeat = bstream.readBits(7) + 11;
|
var repeat = bstream.readBits(7) + 11;
|
||||||
while (repeat--) {
|
while (repeat--) {
|
||||||
literalCodeLengths.push(0);
|
literalCodeLengths.push(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now split the distance code lengths out of the literal code array
|
// now split the distance code lengths out of the literal code array
|
||||||
var distanceCodeLengths = literalCodeLengths.splice(numLiteralLengthCodes, numDistanceCodes);
|
var distanceCodeLengths = literalCodeLengths.splice(numLiteralLengthCodes, numDistanceCodes);
|
||||||
|
|
||||||
// now generate the true Huffman Code tables using these code lengths
|
// now generate the true Huffman Code tables using these code lengths
|
||||||
var hcLiteralTable = getHuffmanCodes(literalCodeLengths),
|
var hcLiteralTable = getHuffmanCodes(literalCodeLengths),
|
||||||
hcDistanceTable = getHuffmanCodes(distanceCodeLengths);
|
hcDistanceTable = getHuffmanCodes(distanceCodeLengths);
|
||||||
blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer);
|
blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer);
|
||||||
}
|
}
|
||||||
// error
|
// error
|
||||||
else {
|
else {
|
||||||
err("Error! Encountered deflate block of type 3");
|
err("Error! Encountered deflate block of type 3");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update progress
|
// update progress
|
||||||
currentBytesUnarchivedInFile += blockSize;
|
currentBytesUnarchivedInFile += blockSize;
|
||||||
currentBytesUnarchived += blockSize;
|
currentBytesUnarchived += blockSize;
|
||||||
postProgress();
|
postProgress();
|
||||||
|
|
||||||
} while (bFinal != 1);
|
} while (bFinal != 1);
|
||||||
// we are done reading blocks if the bFinal bit was set for this block
|
// we are done reading blocks if the bFinal bit was set for this block
|
||||||
|
|
||||||
// return the buffer data bytes
|
// return the buffer data bytes
|
||||||
return buffer.data;
|
return buffer.data;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue