react / wstein / node_modules / browserify / node_modules / browserify-zlib / node_modules / pako / lib / inflate.js
80540 views'use strict';123var zlib_inflate = require('./zlib/inflate.js');4var utils = require('./utils/common');5var strings = require('./utils/strings');6var c = require('./zlib/constants');7var msg = require('./zlib/messages');8var zstream = require('./zlib/zstream');9var gzheader = require('./zlib/gzheader');1011var toString = Object.prototype.toString;1213/**14* class Inflate15*16* Generic JS-style wrapper for zlib calls. If you don't need17* streaming behaviour - use more simple functions: [[inflate]]18* and [[inflateRaw]].19**/2021/* internal22* inflate.chunks -> Array23*24* Chunks of output data, if [[Inflate#onData]] not overriden.25**/2627/**28* Inflate.result -> Uint8Array|Array|String29*30* Uncompressed result, generated by default [[Inflate#onData]]31* and [[Inflate#onEnd]] handlers. Filled after you push last chunk32* (call [[Inflate#push]] with `Z_FINISH` / `true` param).33**/3435/**36* Inflate.err -> Number37*38* Error code after inflate finished. 0 (Z_OK) on success.39* Should be checked if broken data possible.40**/4142/**43* Inflate.msg -> String44*45* Error message, if [[Inflate.err]] != 046**/474849/**50* new Inflate(options)51* - options (Object): zlib inflate options.52*53* Creates new inflator instance with specified params. Throws exception54* on bad params. Supported options:55*56* - `windowBits`57*58* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)59* for more information on these.60*61* Additional options, for internal needs:62*63* - `chunkSize` - size of generated data chunks (16K by default)64* - `raw` (Boolean) - do raw inflate65* - `to` (String) - if equal to 'string', then result will be converted66* from utf8 to utf16 (javascript) string. When string output requested,67* chunk length can differ from `chunkSize`, depending on content.68*69* By default, when no options set, autodetect deflate/gzip data format via70* wrapper header.71*72* ##### Example:73*74* ```javascript75* var pako = require('pako')76* , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])77* , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);78*79* var inflate = new pako.Inflate({ level: 3});80*81* inflate.push(chunk1, false);82* inflate.push(chunk2, true); // true -> last chunk83*84* if (inflate.err) { throw new Error(inflate.err); }85*86* console.log(inflate.result);87* ```88**/89var Inflate = function(options) {9091this.options = utils.assign({92chunkSize: 16384,93windowBits: 0,94to: ''95}, options || {});9697var opt = this.options;9899// Force window size for `raw` data, if not set directly,100// because we have no header for autodetect.101if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {102opt.windowBits = -opt.windowBits;103if (opt.windowBits === 0) { opt.windowBits = -15; }104}105106// If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate107if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&108!(options && options.windowBits)) {109opt.windowBits += 32;110}111112// Gzip header has no info about windows size, we can do autodetect only113// for deflate. So, if window size not set, force it to max when gzip possible114if ((opt.windowBits > 15) && (opt.windowBits < 48)) {115// bit 3 (16) -> gzipped data116// bit 4 (32) -> autodetect gzip/deflate117if ((opt.windowBits & 15) === 0) {118opt.windowBits |= 15;119}120}121122this.err = 0; // error code, if happens (0 = Z_OK)123this.msg = ''; // error message124this.ended = false; // used to avoid multiple onEnd() calls125this.chunks = []; // chunks of compressed data126127this.strm = new zstream();128this.strm.avail_out = 0;129130var status = zlib_inflate.inflateInit2(131this.strm,132opt.windowBits133);134135if (status !== c.Z_OK) {136throw new Error(msg[status]);137}138139this.header = new gzheader();140141zlib_inflate.inflateGetHeader(this.strm, this.header);142};143144/**145* Inflate#push(data[, mode]) -> Boolean146* - data (Uint8Array|Array|ArrayBuffer|String): input data147* - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.148* See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.149*150* Sends input data to inflate pipe, generating [[Inflate#onData]] calls with151* new output chunks. Returns `true` on success. The last data block must have152* mode Z_FINISH (or `true`). That flush internal pending buffers and call153* [[Inflate#onEnd]].154*155* On fail call [[Inflate#onEnd]] with error code and return false.156*157* We strongly recommend to use `Uint8Array` on input for best speed (output158* format is detected automatically). Also, don't skip last param and always159* use the same type in your code (boolean or number). That will improve JS speed.160*161* For regular `Array`-s make sure all elements are [0..255].162*163* ##### Example164*165* ```javascript166* push(chunk, false); // push one of data chunks167* ...168* push(chunk, true); // push last chunk169* ```170**/171Inflate.prototype.push = function(data, mode) {172var strm = this.strm;173var chunkSize = this.options.chunkSize;174var status, _mode;175var next_out_utf8, tail, utf8str;176177if (this.ended) { return false; }178_mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH);179180// Convert data if needed181if (typeof data === 'string') {182// Only binary strings can be decompressed on practice183strm.input = strings.binstring2buf(data);184} else if (toString.call(data) === '[object ArrayBuffer]') {185strm.input = new Uint8Array(data);186} else {187strm.input = data;188}189190strm.next_in = 0;191strm.avail_in = strm.input.length;192193do {194if (strm.avail_out === 0) {195strm.output = new utils.Buf8(chunkSize);196strm.next_out = 0;197strm.avail_out = chunkSize;198}199200status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */201202if (status !== c.Z_STREAM_END && status !== c.Z_OK) {203this.onEnd(status);204this.ended = true;205return false;206}207208if (strm.next_out) {209if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) {210211if (this.options.to === 'string') {212213next_out_utf8 = strings.utf8border(strm.output, strm.next_out);214215tail = strm.next_out - next_out_utf8;216utf8str = strings.buf2string(strm.output, next_out_utf8);217218// move tail219strm.next_out = tail;220strm.avail_out = chunkSize - tail;221if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }222223this.onData(utf8str);224225} else {226this.onData(utils.shrinkBuf(strm.output, strm.next_out));227}228}229}230} while ((strm.avail_in > 0) && status !== c.Z_STREAM_END);231232if (status === c.Z_STREAM_END) {233_mode = c.Z_FINISH;234}235// Finalize on the last chunk.236if (_mode === c.Z_FINISH) {237status = zlib_inflate.inflateEnd(this.strm);238this.onEnd(status);239this.ended = true;240return status === c.Z_OK;241}242243return true;244};245246247/**248* Inflate#onData(chunk) -> Void249* - chunk (Uint8Array|Array|String): ouput data. Type of array depends250* on js engine support. When string output requested, each chunk251* will be string.252*253* By default, stores data blocks in `chunks[]` property and glue254* those in `onEnd`. Override this handler, if you need another behaviour.255**/256Inflate.prototype.onData = function(chunk) {257this.chunks.push(chunk);258};259260261/**262* Inflate#onEnd(status) -> Void263* - status (Number): inflate status. 0 (Z_OK) on success,264* other if not.265*266* Called once after you tell inflate that input stream complete267* or error happenned. By default - join collected chunks,268* free memory and fill `results` / `err` properties.269**/270Inflate.prototype.onEnd = function(status) {271// On success - join272if (status === c.Z_OK) {273if (this.options.to === 'string') {274// Glue & convert here, until we teach pako to send275// utf8 alligned strings to onData276this.result = this.chunks.join('');277} else {278this.result = utils.flattenChunks(this.chunks);279}280}281this.chunks = [];282this.err = status;283this.msg = this.strm.msg;284};285286287/**288* inflate(data[, options]) -> Uint8Array|Array|String289* - data (Uint8Array|Array|String): input data to decompress.290* - options (Object): zlib inflate options.291*292* Decompress `data` with inflate/ungzip and `options`. Autodetect293* format via wrapper header by default. That's why we don't provide294* separate `ungzip` method.295*296* Supported options are:297*298* - windowBits299*300* [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)301* for more information.302*303* Sugar (options):304*305* - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify306* negative windowBits implicitly.307* - `to` (String) - if equal to 'string', then result will be converted308* from utf8 to utf16 (javascript) string. When string output requested,309* chunk length can differ from `chunkSize`, depending on content.310*311*312* ##### Example:313*314* ```javascript315* var pako = require('pako')316* , input = pako.deflate([1,2,3,4,5,6,7,8,9])317* , output;318*319* try {320* output = pako.inflate(input);321* } catch (err)322* console.log(err);323* }324* ```325**/326function inflate(input, options) {327var inflator = new Inflate(options);328329inflator.push(input, true);330331// That will never happens, if you don't cheat with options :)332if (inflator.err) { throw inflator.msg; }333334return inflator.result;335}336337338/**339* inflateRaw(data[, options]) -> Uint8Array|Array|String340* - data (Uint8Array|Array|String): input data to decompress.341* - options (Object): zlib inflate options.342*343* The same as [[inflate]], but creates raw data, without wrapper344* (header and adler32 crc).345**/346function inflateRaw(input, options) {347options = options || {};348options.raw = true;349return inflate(input, options);350}351352353/**354* ungzip(data[, options]) -> Uint8Array|Array|String355* - data (Uint8Array|Array|String): input data to decompress.356* - options (Object): zlib inflate options.357*358* Just shortcut to [[inflate]], because it autodetects format359* by header.content. Done for convenience.360**/361362363exports.Inflate = Inflate;364exports.inflate = inflate;365exports.inflateRaw = inflateRaw;366exports.ungzip = inflate;367368369