diff --git a/lib/zlib/adler32.js b/lib/zlib/adler32.js new file mode 100644 index 0000000..4fc7b4c --- /dev/null +++ b/lib/zlib/adler32.js @@ -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= 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>> 0; +} + +module.exports = adler32; \ No newline at end of file diff --git a/lib/zlib/constants.js b/lib/zlib/constants.js index 5878714..b8968e6 100644 --- a/lib/zlib/constants.js +++ b/lib/zlib/constants.js @@ -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 } \ No newline at end of file diff --git a/lib/zlib/deflate.js b/lib/zlib/deflate.js index a3abded..b5fe227 100644 --- a/lib/zlib/deflate.js +++ b/lib/zlib/deflate.js @@ -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; } /* =========================================================================== diff --git a/lib/zlib/zstream.js b/lib/zlib/zstream.js index 05c004a..a134df7 100644 --- a/lib/zlib/zstream.js +++ b/lib/zlib/zstream.js @@ -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 */