mirror of
https://github.com/0x5eal/rbxts-pako.git
synced 2025-04-03 02:10:57 +01:00
parent
1154023108
commit
bee5019c40
2 changed files with 241 additions and 215 deletions
|
@ -67,13 +67,16 @@ const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
|
|||
|
||||
const PRESET_DICT = 0x20;
|
||||
|
||||
const INIT_STATE = 42;
|
||||
const EXTRA_STATE = 69;
|
||||
const NAME_STATE = 73;
|
||||
const COMMENT_STATE = 91;
|
||||
const HCRC_STATE = 103;
|
||||
const BUSY_STATE = 113;
|
||||
const FINISH_STATE = 666;
|
||||
const INIT_STATE = 42; /* zlib header -> BUSY_STATE */
|
||||
//#ifdef GZIP
|
||||
const GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */
|
||||
//#endif
|
||||
const EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */
|
||||
const NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */
|
||||
const COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */
|
||||
const HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */
|
||||
const BUSY_STATE = 113; /* deflate -> FINISH_STATE */
|
||||
const FINISH_STATE = 666; /* stream complete */
|
||||
|
||||
const BS_NEED_MORE = 1; /* block not completed, need more input or more output */
|
||||
const BS_BLOCK_DONE = 2; /* block flush performed */
|
||||
|
@ -120,11 +123,11 @@ const flush_pending = (strm) => {
|
|||
if (len === 0) { return; }
|
||||
|
||||
strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);
|
||||
strm.next_out += len;
|
||||
s.pending_out += len;
|
||||
strm.next_out += len;
|
||||
s.pending_out += len;
|
||||
strm.total_out += len;
|
||||
strm.avail_out -= len;
|
||||
s.pending -= len;
|
||||
s.pending -= len;
|
||||
if (s.pending === 0) {
|
||||
s.pending_out = 0;
|
||||
}
|
||||
|
@ -1268,6 +1271,9 @@ const deflateStateCheck = (strm) => {
|
|||
}
|
||||
const s = strm.state;
|
||||
if (!s || s.strm !== strm || (s.status !== INIT_STATE &&
|
||||
//#ifdef GZIP
|
||||
s.status !== GZIP_STATE &&
|
||||
//#endif
|
||||
s.status !== EXTRA_STATE &&
|
||||
s.status !== NAME_STATE &&
|
||||
s.status !== COMMENT_STATE &&
|
||||
|
@ -1297,7 +1303,11 @@ const deflateResetKeep = (strm) => {
|
|||
s.wrap = -s.wrap;
|
||||
/* was made negative by deflate(..., Z_FINISH); */
|
||||
}
|
||||
s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
|
||||
s.status =
|
||||
//#ifdef GZIP
|
||||
s.wrap === 2 ? GZIP_STATE :
|
||||
//#endif
|
||||
s.wrap ? INIT_STATE : BUSY_STATE;
|
||||
strm.adler = (s.wrap === 2) ?
|
||||
0 // crc32(0, Z_NULL, 0)
|
||||
:
|
||||
|
@ -1414,10 +1424,9 @@ const deflateInit = (strm, level) => {
|
|||
};
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
const deflate = (strm, flush) => {
|
||||
|
||||
let beg, val; // for gzip header write only
|
||||
|
||||
if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
|
||||
return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
|
||||
}
|
||||
|
@ -1430,210 +1439,9 @@ const deflate = (strm, flush) => {
|
|||
return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
|
||||
}
|
||||
|
||||
s.strm = strm; /* just in case */
|
||||
const old_flush = s.last_flush;
|
||||
s.last_flush = flush;
|
||||
|
||||
/* Write the header */
|
||||
if (s.status === INIT_STATE) {
|
||||
|
||||
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 >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, OS_CODE);
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
else {
|
||||
put_byte(s, (s.gzhead.text ? 1 : 0) +
|
||||
(s.gzhead.hcrc ? 2 : 0) +
|
||||
(!s.gzhead.extra ? 0 : 4) +
|
||||
(!s.gzhead.name ? 0 : 8) +
|
||||
(!s.gzhead.comment ? 0 : 16)
|
||||
);
|
||||
put_byte(s, s.gzhead.time & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 8) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 16) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 24) & 0xff);
|
||||
put_byte(s, s.level === 9 ? 2 :
|
||||
(s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, s.gzhead.os & 0xff);
|
||||
if (s.gzhead.extra && s.gzhead.extra.length) {
|
||||
put_byte(s, s.gzhead.extra.length & 0xff);
|
||||
put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
|
||||
}
|
||||
if (s.gzhead.hcrc) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
|
||||
}
|
||||
s.gzindex = 0;
|
||||
s.status = EXTRA_STATE;
|
||||
}
|
||||
}
|
||||
else // DEFLATE header
|
||||
{
|
||||
let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
|
||||
let level_flags = -1;
|
||||
|
||||
if (s.strategy >= 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//#ifdef GZIP
|
||||
if (s.status === EXTRA_STATE) {
|
||||
if (s.gzhead.extra/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
|
||||
while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
|
||||
s.gzindex++;
|
||||
}
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (s.gzindex === s.gzhead.extra.length) {
|
||||
s.gzindex = 0;
|
||||
s.status = NAME_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = NAME_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === NAME_STATE) {
|
||||
if (s.gzhead.name/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
//int val;
|
||||
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.name.length) {
|
||||
val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (val === 0) {
|
||||
s.gzindex = 0;
|
||||
s.status = COMMENT_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = COMMENT_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === COMMENT_STATE) {
|
||||
if (s.gzhead.comment/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
//int val;
|
||||
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.comment.length) {
|
||||
val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (val === 0) {
|
||||
s.status = HCRC_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = HCRC_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === HCRC_STATE) {
|
||||
if (s.gzhead.hcrc) {
|
||||
if (s.pending + 2 > s.pending_buf_size) {
|
||||
flush_pending(strm);
|
||||
}
|
||||
if (s.pending + 2 <= s.pending_buf_size) {
|
||||
put_byte(s, strm.adler & 0xff);
|
||||
put_byte(s, (strm.adler >> 8) & 0xff);
|
||||
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
/* Flush as much pending output as possible */
|
||||
if (s.pending !== 0) {
|
||||
flush_pending(strm);
|
||||
|
@ -1662,6 +1470,224 @@ const deflate = (strm, flush) => {
|
|||
return err(strm, Z_BUF_ERROR);
|
||||
}
|
||||
|
||||
/* Write the header */
|
||||
if (s.status === INIT_STATE) {
|
||||
/* zlib header */
|
||||
let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
|
||||
let level_flags = -1;
|
||||
|
||||
if (s.strategy >= 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);
|
||||
|
||||
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);
|
||||
s.status = BUSY_STATE;
|
||||
|
||||
/* Compression must start with an empty pending buffer */
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
}
|
||||
//#ifdef GZIP
|
||||
if (s.status === GZIP_STATE) {
|
||||
/* 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 >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, OS_CODE);
|
||||
s.status = BUSY_STATE;
|
||||
|
||||
/* Compression must start with an empty pending buffer */
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
put_byte(s, (s.gzhead.text ? 1 : 0) +
|
||||
(s.gzhead.hcrc ? 2 : 0) +
|
||||
(!s.gzhead.extra ? 0 : 4) +
|
||||
(!s.gzhead.name ? 0 : 8) +
|
||||
(!s.gzhead.comment ? 0 : 16)
|
||||
);
|
||||
put_byte(s, s.gzhead.time & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 8) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 16) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 24) & 0xff);
|
||||
put_byte(s, s.level === 9 ? 2 :
|
||||
(s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, s.gzhead.os & 0xff);
|
||||
if (s.gzhead.extra && s.gzhead.extra.length) {
|
||||
put_byte(s, s.gzhead.extra.length & 0xff);
|
||||
put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
|
||||
}
|
||||
if (s.gzhead.hcrc) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
|
||||
}
|
||||
s.gzindex = 0;
|
||||
s.status = EXTRA_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === EXTRA_STATE) {
|
||||
if (s.gzhead.extra/* != Z_NULL*/) {
|
||||
let beg = s.pending; /* start of bytes to update crc */
|
||||
let left = (s.gzhead.extra.length & 0xffff) - s.gzindex;
|
||||
while (s.pending + left > s.pending_buf_size) {
|
||||
let copy = s.pending_buf_size - s.pending;
|
||||
// zmemcpy(s.pending_buf + s.pending,
|
||||
// s.gzhead.extra + s.gzindex, copy);
|
||||
s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending);
|
||||
s.pending = s.pending_buf_size;
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
s.gzindex += copy;
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
beg = 0;
|
||||
left -= copy;
|
||||
}
|
||||
// zmemcpy(s->pending_buf + s->pending,
|
||||
// s->gzhead->extra + s->gzindex, left);
|
||||
s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + left), s.pending);
|
||||
s.pending += left;
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
s.gzindex = 0;
|
||||
}
|
||||
s.status = NAME_STATE;
|
||||
}
|
||||
if (s.status === NAME_STATE) {
|
||||
if (s.gzhead.name/* != Z_NULL*/) {
|
||||
let beg = s.pending; /* start of bytes to update crc */
|
||||
let val;
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
beg = 0;
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.name.length) {
|
||||
val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
s.gzindex = 0;
|
||||
}
|
||||
s.status = COMMENT_STATE;
|
||||
}
|
||||
if (s.status === COMMENT_STATE) {
|
||||
if (s.gzhead.comment/* != Z_NULL*/) {
|
||||
let beg = s.pending; /* start of bytes to update crc */
|
||||
let val;
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
beg = 0;
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.comment.length) {
|
||||
val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
//--- HCRC_UPDATE(beg) ---//
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
//---//
|
||||
}
|
||||
s.status = HCRC_STATE;
|
||||
}
|
||||
if (s.status === HCRC_STATE) {
|
||||
if (s.gzhead.hcrc) {
|
||||
if (s.pending + 2 > s.pending_buf_size) {
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
}
|
||||
put_byte(s, strm.adler & 0xff);
|
||||
put_byte(s, (strm.adler >> 8) & 0xff);
|
||||
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
||||
}
|
||||
s.status = BUSY_STATE;
|
||||
|
||||
/* Compression must start with an empty pending buffer */
|
||||
flush_pending(strm);
|
||||
if (s.pending !== 0) {
|
||||
s.last_flush = -1;
|
||||
return Z_OK;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
/* Start a new block or continue the current one.
|
||||
*/
|
||||
if (strm.avail_in !== 0 || s.lookahead !== 0 ||
|
||||
|
|
|
@ -38,7 +38,7 @@ describe('Gzip special cases', () => {
|
|||
os: 15,
|
||||
name: 'test name',
|
||||
comment: 'test comment',
|
||||
extra: [ 4, 5, 6 ]
|
||||
extra: new Uint8Array([ 4, 5, 6 ])
|
||||
}
|
||||
});
|
||||
deflator.push(data, true);
|
||||
|
|
Loading…
Add table
Reference in a new issue