mirror of
https://github.com/0x5eal/rbxts-pako.git
synced 2025-04-04 10:50:59 +01:00
Added gzip interface (without custom headers support)
This commit is contained in:
parent
1b3f7253a8
commit
285e2d4cff
4 changed files with 128 additions and 52 deletions
|
@ -31,6 +31,10 @@ var Deflate = function(options) {
|
|||
opt.windowBits = -opt.windowBits;
|
||||
}
|
||||
|
||||
else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
|
||||
opt.windowBits += 16;
|
||||
}
|
||||
|
||||
this.strm = new zstream();
|
||||
|
||||
var status = zlib_deflate.deflateInit2(
|
||||
|
@ -159,6 +163,14 @@ function deflateRaw(input, options) {
|
|||
}
|
||||
|
||||
|
||||
function gzip(input, options) {
|
||||
options = options || {};
|
||||
options.gzip = true;
|
||||
return deflate(input, options);
|
||||
}
|
||||
|
||||
|
||||
exports.Deflate = Deflate;
|
||||
exports.deflate = deflate;
|
||||
exports.deflateRaw = deflateRaw;
|
||||
exports.deflateRaw = deflateRaw;
|
||||
exports.gzip = gzip;
|
|
@ -1,9 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
// CRC table.
|
||||
// Use ordinary array, since untyped makes no boost here
|
||||
//
|
||||
var crcTable = function makeTable() {
|
||||
function makeTable() {
|
||||
var c, table = [];
|
||||
|
||||
for(var n =0; n < 256; n++){
|
||||
|
@ -15,16 +13,20 @@ var crcTable = function makeTable() {
|
|||
}
|
||||
|
||||
return table;
|
||||
} ();
|
||||
}
|
||||
|
||||
|
||||
var crcTable = makeTable();
|
||||
|
||||
|
||||
function crc32(crc, buf, len, pos) {
|
||||
var t = crcTable,
|
||||
, end = pos + len
|
||||
, crc = 0 ^ (-1);
|
||||
var t = crcTable
|
||||
, end = pos + len;
|
||||
|
||||
crc = 0 ^ (-1);
|
||||
|
||||
for (var i = pos; i < end; i++ ) {
|
||||
crc = (crc >>> 8) ^ t[(crc ^ input[i]) & 0xFF];
|
||||
crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
|
||||
}
|
||||
|
||||
return (crc ^ (-1)); // >>> 0;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var c = require('./constants');
|
||||
var utils = require('./utils');
|
||||
var trees = require('./trees');
|
||||
var c = require('./constants');
|
||||
var utils = require('./utils');
|
||||
var trees = require('./trees');
|
||||
var adler32 = require('./adler32');
|
||||
var crc32 = require('./crc32');
|
||||
|
||||
var Z_NULL = c.Z_NULL;
|
||||
|
||||
|
@ -30,6 +31,8 @@ var BS_BLOCK_DONE = 2; /* block flush performed */
|
|||
var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
|
||||
var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
|
||||
|
||||
var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
|
||||
|
||||
function rank (f) {
|
||||
return ((f) << 1) - ((f) > 4 ? 9 : 0);
|
||||
}
|
||||
|
@ -71,6 +74,10 @@ function update_hash (s, h, c) {
|
|||
return (((h) << s.hash_shift) ^ (c)) & s.hash_mask;
|
||||
}
|
||||
|
||||
function put_byte(s, b) {
|
||||
s.pending_buf[s.pending++] = b;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* Put a short in the pending buffer. The 16-bit value is put in MSB order.
|
||||
* IN assertion: the stream state is correct and there is enough room in
|
||||
|
@ -102,6 +109,11 @@ function read_buf(strm, buf, start, size) {
|
|||
if (strm.state.wrap === 1) {
|
||||
strm.adler = adler32(strm.adler, buf, len, start);
|
||||
}
|
||||
|
||||
else if (strm.state.wrap === 2) {
|
||||
strm.adler = crc32(strm.adler, buf, len, start);
|
||||
}
|
||||
|
||||
strm.next_in_index += len;
|
||||
strm.total_in += len;
|
||||
|
||||
|
@ -464,9 +476,9 @@ function DeflateState() {
|
|||
this.pending_out = 0; /* next pending byte to output to the stream */
|
||||
this.pending = 0; /* nb of bytes in the pending buffer */
|
||||
this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
// gz_headerp gzhead; /* gzip header information to write */
|
||||
// uInt gzindex; /* where in extra, name, or comment */
|
||||
// Byte method; /* can only be DEFLATED */
|
||||
this.gzhead = null; /* gzip header information to write */
|
||||
this.gzindex = 0; /* where in extra, name, or comment */
|
||||
this.method = c.Z_DEFLATED; /* can only be DEFLATED */
|
||||
this.last_flush = Z_NULL; /* value of flush param for previous deflate call */
|
||||
|
||||
this.w_size = 0; /* LZ77 window size (32K by default) */
|
||||
|
@ -563,7 +575,10 @@ function deflateResetKeep(strm) {
|
|||
/* was made negative by deflate(..., Z_FINISH); */
|
||||
}
|
||||
s.status = s.wrap ? INIT_STATE : BUSY_STATE;
|
||||
strm.adler = 1; // adler32(0, Z_NULL, 0);
|
||||
strm.adler = (s.wrap === 2) ?
|
||||
0 // crc32(0, Z_NULL, 0)
|
||||
:
|
||||
1; // adler32(0, Z_NULL, 0)
|
||||
s.last_flush = c.Z_NO_FLUSH;
|
||||
trees._tr_init(s);
|
||||
return c.Z_OK;
|
||||
|
@ -592,6 +607,11 @@ function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
|
|||
windowBits = -windowBits;
|
||||
}
|
||||
|
||||
else if (windowBits > 15) {
|
||||
wrap = 2; /* write gzip wrapper instead */
|
||||
windowBits -= 16;
|
||||
}
|
||||
|
||||
if (windowBits === 8) {
|
||||
windowBits = 9;
|
||||
}
|
||||
|
@ -603,22 +623,27 @@ function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
|
|||
s.strm = strm;
|
||||
|
||||
s.wrap = wrap;
|
||||
s.gzhead = Z_NULL;
|
||||
s.gzhead = null;
|
||||
s.w_bits = windowBits;
|
||||
s.w_size = 1 << s.w_bits;
|
||||
s.w_mask = s.w_size - 1;
|
||||
|
||||
s.window = utils.arrayCreate(s.w_size * 2);
|
||||
|
||||
s.hash_bits = memLevel + 7;
|
||||
s.hash_size = 1 << s.hash_bits;
|
||||
s.hash_mask = s.hash_size - 1;
|
||||
s.hash_shift = (s.hash_bits + MIN_MATCH - 1) / MIN_MATCH;
|
||||
|
||||
s.high_water = 0;
|
||||
/* nothing written to s->window yet */
|
||||
s.lit_bufsize = 1 << (memLevel + 6);
|
||||
/* 16K elements by default */
|
||||
s.window = utils.arrayCreate(s.w_size * 2);
|
||||
s.head = utils.array16Create(s.hash_size);
|
||||
s.prev = utils.array16Create(s.w_size);
|
||||
// precreate & prefill head/prev arrays to optimize v8 types
|
||||
// TODO: check if we can remove it, should be inited in lm_init()
|
||||
utils.fill(s.head, 0);
|
||||
utils.fill(s.prev, 0);
|
||||
|
||||
s.high_water = 0; /* nothing written to s->window yet */
|
||||
|
||||
s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
|
||||
|
||||
s.pending_buf_size = s.lit_bufsize * 4;
|
||||
s.pending_buf = utils.arrayCreate(s.pending_buf_size);
|
||||
|
@ -627,12 +652,6 @@ function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
|
|||
s.strategy = strategy;
|
||||
s.method = method;
|
||||
|
||||
// precreate & prefill head/prev arrays to optimize v8 types
|
||||
s.head = utils.array16Create(s.hash_size);
|
||||
s.prev = utils.array16Create(s.w_size);
|
||||
utils.fill(s.head, 0);
|
||||
utils.fill(s.prev, 0);
|
||||
|
||||
return deflateReset(strm);
|
||||
}
|
||||
|
||||
|
@ -681,31 +700,55 @@ function deflate(strm, flush) {
|
|||
/* Write the header */
|
||||
if (s.status === INIT_STATE) {
|
||||
|
||||
var header = (c.Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
|
||||
var level_flags = -1;
|
||||
|
||||
if (s.strategy >= c.Z_HUFFMAN_ONLY || s.level < 2) {
|
||||
level_flags = 0;
|
||||
} else if (s.level < 6) {
|
||||
level_flags = 1;
|
||||
} else if (s.level === 6) {
|
||||
level_flags = 2;
|
||||
} else {
|
||||
level_flags = 3;
|
||||
if (s.wrap === 2) { // GZIP header
|
||||
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
||||
put_byte(s, 31);
|
||||
put_byte(s, 139);
|
||||
put_byte(s, 8);
|
||||
if (!s.gzhead) { // s->gzhead == Z_NULL
|
||||
put_byte(s, 0);
|
||||
put_byte(s, 0);
|
||||
put_byte(s, 0);
|
||||
put_byte(s, 0);
|
||||
put_byte(s, 0);
|
||||
put_byte(s, s.level === 9 ? 2 :
|
||||
(s.strategy >= c.Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, OS_CODE);
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
else {
|
||||
throw new Error('Custom GZIP headers not supported');
|
||||
}
|
||||
}
|
||||
header |= (level_flags << 6);
|
||||
if (s.strstart !== 0) { header |= PRESET_DICT; }
|
||||
header += 31 - (header % 31);
|
||||
else // DEFLATE header
|
||||
{
|
||||
var header = (c.Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
|
||||
var level_flags = -1;
|
||||
|
||||
s.status = BUSY_STATE;
|
||||
putShortMSB(s, header);
|
||||
if (s.strategy >= c.Z_HUFFMAN_ONLY || s.level < 2) {
|
||||
level_flags = 0;
|
||||
} else if (s.level < 6) {
|
||||
level_flags = 1;
|
||||
} else if (s.level === 6) {
|
||||
level_flags = 2;
|
||||
} else {
|
||||
level_flags = 3;
|
||||
}
|
||||
header |= (level_flags << 6);
|
||||
if (s.strstart !== 0) { header |= PRESET_DICT; }
|
||||
header += 31 - (header % 31);
|
||||
|
||||
/* Save the adler32 of the preset dictionary: */
|
||||
if (s.strstart !== 0) {
|
||||
putShortMSB(s, strm.adler >>> 16);
|
||||
putShortMSB(s, strm.adler & 0xffff);
|
||||
s.status = BUSY_STATE;
|
||||
putShortMSB(s, header);
|
||||
|
||||
/* Save the adler32 of the preset dictionary: */
|
||||
if (s.strstart !== 0) {
|
||||
putShortMSB(s, strm.adler >>> 16);
|
||||
putShortMSB(s, strm.adler & 0xffff);
|
||||
}
|
||||
strm.adler = 1; // adler32(0L, Z_NULL, 0);
|
||||
}
|
||||
strm.adler = 1; // adler32(0L, Z_NULL, 0);
|
||||
}
|
||||
|
||||
/* Flush as much pending output as possible */
|
||||
|
@ -796,8 +839,22 @@ function deflate(strm, flush) {
|
|||
if (flush !== c.Z_FINISH) { return c.Z_OK; }
|
||||
if (s.wrap <= 0) { return c.Z_STREAM_END; }
|
||||
|
||||
putShortMSB(s, strm.adler >>> 16);
|
||||
putShortMSB(s, strm.adler & 0xffff);
|
||||
/* Write the trailer */
|
||||
if (s.wrap === 2) {
|
||||
put_byte(s, strm.adler & 0xff);
|
||||
put_byte(s, (strm.adler >> 8) & 0xff);
|
||||
put_byte(s, (strm.adler >> 16) & 0xff);
|
||||
put_byte(s, (strm.adler >> 24) & 0xff);
|
||||
put_byte(s, strm.total_in & 0xff);
|
||||
put_byte(s, (strm.total_in >> 8) & 0xff);
|
||||
put_byte(s, (strm.total_in >> 16) & 0xff);
|
||||
put_byte(s, (strm.total_in >> 24) & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
putShortMSB(s, strm.adler >>> 16);
|
||||
putShortMSB(s, strm.adler & 0xffff);
|
||||
}
|
||||
|
||||
flush_pending(strm);
|
||||
/* If avail_out is zero, the application will call deflate again
|
||||
|
|
|
@ -32,6 +32,11 @@ describe('Deflate defaults', function () {
|
|||
testDeflate(zlib.createDeflateRaw, pako.deflateRaw, sample, { level: 0 }, done);
|
||||
});
|
||||
|
||||
// OS_CODE can differ. Probably should add param to compare function
|
||||
// to ignore some buffer positions
|
||||
it.skip('gzip (level 0)', function(done) {
|
||||
testDeflate(zlib.createGzip, pako.gzip, sample, { level: 0 }, done);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue