add adler32 algoritm

implementation of deflate init methods
This commit is contained in:
nik 2014-02-04 19:08:26 -02:00
parent ff0a4c0c50
commit b4919faf9a
4 changed files with 215 additions and 15 deletions

65
lib/zlib/adler32.js Normal file
View file

@ -0,0 +1,65 @@
'use strict';
var BASE = 65521; /* largest prime smaller than 65536 */
var NMAX = 5552;
function adler32(adler, buf, len)
{
var i = 0;
/* split Adler-32 into component sums */
var sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return (adler | (sum2 << 16)) >>> 0;
}
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
for(i=0;i<len;i++) {
adler += buf[i];
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
sum2 %= BASE; /* only added so many BASE's */
return (adler | (sum2 << 16)) >>> 0;
}
var cursor = 0;
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
var next_cursor = cursor + NMAX;
for (i=cursor;i<next_cursor;i++) {
adler += buf[i];
sum2 += adler;
}
adler %= BASE;
sum2 %= BASE;
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
for (i=cursor;i<len;i++) {
adler += buf[i];
sum2 += adler;
}
adler %= BASE;
sum2 %= BASE;
}
/* return recombined sums */
return (adler | (sum2 << 16)) >>> 0;
}
module.exports = adler32;

View file

@ -29,5 +29,15 @@ module.exports = {
Z_HUFFMAN_ONLY: 2,
Z_RLE: 3,
Z_FIXED: 4,
Z_DEFAULT_STRATEGY: 0
Z_DEFAULT_STRATEGY: 0,
Z_BINARY: 0,
Z_TEXT: 1,
Z_ASCII: 1, // = Z_TEXT
Z_UNKNOWN: 2,
/* Possible values of the data_type field (though see inflate()) */
Z_DEFLATED: 8,
/* The deflate compression method */
Z_NULL: 0
}

View file

@ -1,18 +1,71 @@
var consts = require('constants');
var c = require('./constants');
var adler32 = require('./adler32');
function internal_state() {
var FASTEST = true;
var Z_NULL = c.Z_NULL;
var MAX_WBITS = 15; /* 32K LZ77 window */
var DEF_MEM_LEVEL = 8;
var MIN_MATCH = 3;
var MAX_MATCH = 258;
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
var INIT_STATE = 42;
var EXTRA_STATE = 69;
var NAME_STATE = 73;
var COMMENT_STATE = 91;
var HCRC_STATE = 103;
var BUSY_STATE = 113;
var FINISH_STATE = 666;
var config = function(good_length,max_lazy,nice_length,max_chain,func) {
this.good_length = good_length;
this.max_lazy = max_lazy;
this.nice_length = nice_length;
this.max_chain = max_chain;
this.func = func;
}
var configuration_table;
if (FASTEST) {
configuration_table = [
/* good lazy nice chain */
/* 0 */ new config(0, 0, 0, 0, deflate_stored), /* store only */
/* 1 */ new config(4, 4, 8, 4, deflate_fast) /* max speed, no lazy matches */
]
} else {
configuration_table = [
/* good lazy nice chain */
/* 0 */ new config(0, 0, 0, 0, deflate_stored), /* store only */
/* 1 */ new config(4, 4, 8, 4, deflate_fast), /* max speed, no lazy matches */
/* 2 */ new config(4, 5, 16, 8, deflate_fast),
/* 3 */ new config(4, 6, 32, 32, deflate_fast),
/* 4 */ new config(4, 4, 16, 16, deflate_slow), /* lazy matches */
/* 5 */ new config(8, 16, 32, 32, deflate_slow),
/* 6 */ new config(8, 16, 128, 128, deflate_slow),
/* 7 */ new config(8, 32, 128, 256, deflate_slow),
/* 8 */ new config(32, 128, 258, 1024, deflate_slow),
/* 9 */ new config(32, 258, 258, 4096, deflate_slow) /* max compression */
]
}
function deflate_state() {
this.status = 0; /* as the name implies */
this.pending_buf = -1; /* output still pending */
this.pending_buf = Z_NULL; /* output still pending */
this.pending_buf_size = 0; /* size of pending_buf */
this.pending_out = -1; /* next pending byte to output to the stream */
this.pending_out = Z_NULL; /* next pending byte to output to the stream */
this.pending = 0; /* nb of bytes in the pending buffer */
this.last_flush = -1; /* value of flush param for previous deflate call */
this.last_flush = Z_NULL; /* value of flush param for previous deflate call */
this.w_size = 0; /* LZ77 window size (32K by default) */
this.w_bits = 0; /* log2(w_size) (8..16) */
this.w_mask = 0; /* w_size - 1 */
this.window = -1;
this.window = Z_NULL;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
@ -25,13 +78,13 @@ function internal_state() {
* is directly used as sliding window.
*/
this.prev = -1;
this.prev = Z_NULL;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
this.head = -1; /* Heads of the hash chains or NIL. */
this.head = Z_NULL; /* Heads of the hash chains or NIL. */
this.ins_h = 0; /* hash index of string to be inserted */
this.hash_size = 0; /* number of elements in hash table */
@ -89,11 +142,49 @@ function internal_state() {
}
function deflateInit (strm, level) {
return deflateInit2(strm, level, c.Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,c.Z_DEFAULT_STRATEGY);
}
function deflateInit2 (strm, level, method, windowBits, memLevel, strategy) {
if (strm == Z_NULL) return c.Z_STREAM_ERROR;
if(FASTEST) {
if (level != 0) level = 1;
} else {
if (level == c.Z_DEFAULT_COMPRESSION) level = 6;
}
if (windowBits < 0) { /* suppress zlib wrapper */
wrap = 0;
windowBits = -windowBits;
}
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
var s = new deflate_state();
strm.state = s;
s.strm = strm;
s.wrap = wrap;
s.gzhead = Z_NULL;
s.w_bits = windowBits;
s.w_size = 1 << s.w_bits;
s.w_mask = s.w_size - 1;
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.level = level;
s.strategy = strategy;
s.method = method;
return deflateReset(strm);
}
function deflateSetDictionary (strm, dictionary, dictLength) {
@ -101,11 +192,28 @@ function deflateSetDictionary (strm, dictionary, dictLength) {
}
function deflateResetKeep (strm) {
strm.total_in = strm.total_out = 0;
strm.data_type = c.Z_UNKNOWN;
var s = strm.state;
s.pending = 0;
s.pending_out = s.pending_buf;
if (s.wrap < 0) {
s.wrap = -s.wrap; /* was made negative by deflate(..., Z_FINISH); */
}
s.status = s.wrap ? INIT_STATE : BUSY_STATE;
strm.adler = adler32(0, Z_NULL, 0);
s.last_flush = c.Z_NO_FLUSH;
//_tr_init(s);
return c.Z_OK;
}
function deflateReset (strm) {
var ret = deflateResetKeep(strm);
if (ret == c.Z_OK)
lm_init(strm.state);
return ret;
}
function deflateParams (strm,level,strategy) {
@ -173,7 +281,22 @@ function read_buf(strm, buf, size) {
* Initialize the "longest match" routines for a new zlib stream
*/
function lm_init (s) {
s.window_size = 2* s.w_size;
/* Set the default configuration parameters:
*/
s.max_lazy_match = configuration_table[s.level].max_lazy;
s.good_match = configuration_table[s.level].good_length;
s.nice_match = configuration_table[s.level].nice_length;
s.max_chain_length = configuration_table[s.level].max_chain;
s.strstart = 0;
s.block_start = 0;
s.lookahead = 0;
s.insert = 0;
s.match_length = s.prev_length = MIN_MATCH-1;
s.match_available = 0;
s.ins_h = 0;
}
/* ===========================================================================

View file

@ -1,20 +1,22 @@
var c = require('constants');
function ZStream() {
/* next input byte */
this.next_in = -1;
this.next_in = c.Z_NULL;
/* number of bytes available at next_in */
this.avail_in = 0;
/* total number of input bytes read so far */
this.total_in = 0;
/* next output byte should be put there */
this.next_out = -1;
this.next_out = c.Z_NULL;
/* remaining free space at next_out */
this.avail_out = 0;
/* total number of bytes output so far */
this.total_out = 0;
/* last error message, NULL if no error */
this.msg = -1;
this.msg = c.Z_NULL;
/* not visible by applications */
this.state = -1;
this.state = c.Z_NULL;
/* best guess about the data type: binary or text */
this.data_type = 2;
/* adler32 value of the uncompressed data */