formio/node_modules/adm-zip/methods/inflater.js   F
last analyzed

Complexity

Total Complexity 116
Complexity/F 7.73

Size

Lines of Code 448
Function Count 15

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
wmc 116
nc 2
mnd 6
bc 53
fnc 15
dl 0
loc 448
rs 1.5789
bpm 3.5333
cpm 7.7333
noi 19
c 0
b 0
f 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
B inflater.js ➔ JSInflater 0 412 1
B module.exports 0 33 1

How to fix   Complexity   

Complexity

Complex classes like formio/node_modules/adm-zip/methods/inflater.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
var Buffer = require("buffer").Buffer;
2
3
function JSInflater(/*Buffer*/input) {
4
5
    var WSIZE = 0x8000,
6
        slide = new Buffer(0x10000),
7
        windowPos = 0,
8
        fixedTableList = null,
9
        fixedTableDist,
10
        fixedLookup,
11
        bitBuf = 0,
12
        bitLen = 0,
13
        method = -1,
14
        eof = false,
15
        copyLen = 0,
16
        copyDist = 0,
17
        tblList, tblDist, bitList, bitdist,
18
19
        inputPosition = 0,
20
21
        MASK_BITS = [0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff],
22
        LENS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0],
23
        LEXT = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99],
24
        DISTS = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577],
25
        DEXT = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13],
26
        BITORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
27
28
    function HuffTable(clen, cnum, cval, blist, elist, lookupm) {
29
30
        this.status = 0;
31
        this.root = null;
32
        this.maxbit = 0;
33
34
        var el, f, tail,
35
            offsets = [],
36
            countTbl = [],
37
            sTbl = [],
38
            values = [],
39
            tentry = {extra: 0, bitcnt: 0, lbase: 0, next: null};
40
41
        tail = this.root = null;
42
        for(var i = 0; i < 0x11; i++)  { countTbl[i] = 0; sTbl[i] = 0; offsets[i] = 0; }
43
        for(i = 0; i < 0x120; i++) values[i] = 0;
44
45
        el = cnum > 256 ? clen[256] : 16;
46
47
        var pidx = -1;
48
        while (++pidx < cnum) countTbl[clen[pidx]]++;
49
50
        if(countTbl[0] == cnum) return;
51
52
        for(var j = 1; j <= 16; j++) if(countTbl[j] != 0) break;
53
        var bitLen = j;
54
        for(i = 16; i != 0; i--) if(countTbl[i] != 0) break;
55
        var maxLen = i;
56
57
        lookupm < j && (lookupm = j);
58
59
        var dCodes = 1 << j;
60
        for(; j < i; j++, dCodes <<= 1)
61
            if((dCodes -= countTbl[j]) < 0) {
62
                this.status = 2;
63
                this.maxbit = lookupm;
64
                return;
65
            }
66
67
        if((dCodes -= countTbl[i]) < 0) {
68
            this.status = 2;
69
            this.maxbit = lookupm;
70
            return;
71
        }
72
73
        countTbl[i] += dCodes;
74
        offsets[1] = j = 0;
75
        pidx = 1;
76
        var xp = 2;
77
        while(--i > 0) offsets[xp++] = (j += countTbl[pidx++]);
78
        pidx = 0;
79
        i = 0;
80
        do {
81
            (j = clen[pidx++]) && (values[offsets[j]++] = i);
82
        } while(++i < cnum);
83
        cnum = offsets[maxLen];
84
        offsets[0] = i = 0;
85
        pidx = 0;
86
87
        var level = -1,
88
            w = sTbl[0] = 0,
89
            cnode = null,
90
            tblCnt = 0,
91
            tblStack = [];
92
93
        for(; bitLen <= maxLen; bitLen++) {
94
            var kccnt = countTbl[bitLen];
95
            while(kccnt-- > 0) {
96
                while(bitLen > w + sTbl[1 + level]) {
97
                    w += sTbl[1 + level];
98
                    level++;
99
                    tblCnt = (tblCnt = maxLen - w) > lookupm ? lookupm : tblCnt;
100
                    if((f = 1 << (j = bitLen - w)) > kccnt + 1) {
101
                        f -= kccnt + 1;
102
                        xp = bitLen;
103
                        while(++j < tblCnt) {
104
                            if((f <<= 1) <= countTbl[++xp]) break;
105
                            f -= countTbl[xp];
106
                        }
107
                    }
108
                    if(w + j > el && w < el) j = el - w;
109
                    tblCnt = 1 << j;
110
                    sTbl[1 + level] = j;
111
                    cnode = [];
112
                    while (cnode.length < tblCnt) cnode.push({extra: 0, bitcnt: 0, lbase: 0, next: null});
113
                    if (tail == null) {
114
                        tail = this.root = {next:null, list:null};
115
                    } else {
116
                        tail = tail.next = {next:null, list:null}
117
                    }
118
                    tail.next = null;
119
                    tail.list = cnode;
120
121
                    tblStack[level] = cnode;
122
123
                    if(level > 0) {
124
                        offsets[level] = i;
125
                        tentry.bitcnt = sTbl[level];
126
                        tentry.extra = 16 + j;
127
                        tentry.next = cnode;
128
                        j = (i & ((1 << w) - 1)) >> (w - sTbl[level]);
129
130
                        tblStack[level-1][j].extra = tentry.extra;
131
                        tblStack[level-1][j].bitcnt = tentry.bitcnt;
132
                        tblStack[level-1][j].lbase = tentry.lbase;
133
                        tblStack[level-1][j].next = tentry.next;
134
                    }
135
                }
136
                tentry.bitcnt = bitLen - w;
137
                if(pidx >= cnum)
138
                    tentry.extra = 99;
139
                else if(values[pidx] < cval) {
140
                    tentry.extra = (values[pidx] < 256 ? 16 : 15);
141
                    tentry.lbase = values[pidx++];
142
                } else {
143
                    tentry.extra = elist[values[pidx] - cval];
144
                    tentry.lbase = blist[values[pidx++] - cval];
145
                }
146
147
                f = 1 << (bitLen - w);
148
                for(j = i >> w; j < tblCnt; j += f) {
149
                    cnode[j].extra = tentry.extra;
150
                    cnode[j].bitcnt = tentry.bitcnt;
151
                    cnode[j].lbase = tentry.lbase;
152
                    cnode[j].next = tentry.next;
153
                }
154
                for(j = 1 << (bitLen - 1); (i & j) != 0; j >>= 1)
155
                    i ^= j;
156
                i ^= j;
157
                while((i & ((1 << w) - 1)) != offsets[level]) {
158
                    w -= sTbl[level];
159
                    level--;
160
                }
161
            }
162
        }
163
164
        this.maxbit = sTbl[1];
165
        this.status = ((dCodes != 0 && maxLen != 1) ? 1 : 0);
166
    }
167
168
    function addBits(n) {
169
        while(bitLen < n) {
0 ignored issues
show
Bug introduced by
The variable bitLen is changed as part of the while loop for example by 8 on line 171. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
170
            bitBuf |= input[inputPosition++] << bitLen;
0 ignored issues
show
Bug introduced by
The variable bitBuf is changed as part of the while loop for example by input.inputPosition++ << bitLen on line 170. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable inputPosition is changed as part of the while loop for example by inputPosition++ on line 170. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
171
            bitLen += 8;
172
        }
173
        return bitBuf;
174
    }
175
176
    function cutBits(n) {
177
        bitLen -= n;
178
        return bitBuf >>= n;
179
    }
180
181
    function maskBits(n) {
182
        while(bitLen < n) {
0 ignored issues
show
Bug introduced by
The variable bitLen is changed as part of the while loop for example by 8 on line 184. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
183
            bitBuf |= input[inputPosition++] << bitLen;
0 ignored issues
show
Bug introduced by
The variable inputPosition is changed as part of the while loop for example by inputPosition++ on line 183. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable bitBuf is changed as part of the while loop for example by input.inputPosition++ << bitLen on line 183. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
184
            bitLen += 8;
185
        }
186
        var res = bitBuf & MASK_BITS[n];
187
        bitBuf >>= n;
188
        bitLen -= n;
189
        return res;
190
    }
191
192
    function codes(buff, off, size) {
193
        var e, t;
194
        if(size == 0) return 0;
195
196
        var n = 0;
197
        for(;;) {
198
            t = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
199
            e = t.extra;
200
            while(e > 16) {
201
                if(e == 99) return -1;
202
                cutBits(t.bitcnt);
203
                e -= 16;
204
                t = t.next[addBits(e) & MASK_BITS[e]];
205
                e = t.extra;
206
            }
207
            cutBits(t.bitcnt);
208
            if(e == 16) {
209
                windowPos &= WSIZE - 1;
0 ignored issues
show
Bug introduced by
The variable windowPos is changed as part of the for loop for example by windowPos++ on line 210. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
210
                buff[off + n++] = slide[windowPos++] = t.lbase;
211
                if(n == size) return size;
212
                continue;
213
            }
214
            if(e == 15) break;
215
216
            copyLen = t.lbase + maskBits(e);
217
            t = tblDist.list[addBits(bitdist) & MASK_BITS[bitdist]];
218
            e = t.extra;
219
220
            while(e > 16) {
221
                if(e == 99) return -1;
222
                cutBits(t.bitcnt);
223
                e -= 16;
224
                t = t.next[addBits(e) & MASK_BITS[e]];
225
                e = t.extra
226
            }
227
            cutBits(t.bitcnt);
228
            copyDist = windowPos - t.lbase - maskBits(e);
229
230
            while(copyLen > 0 && n < size) {
0 ignored issues
show
Bug introduced by
The variable copyLen is changed as part of the while loop for example by copyLen-- on line 231. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
231
                copyLen--;
232
                copyDist &= WSIZE - 1;
0 ignored issues
show
Bug introduced by
The variable copyDist is changed as part of the while loop for example by copyDist++ on line 234. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
233
                windowPos &= WSIZE - 1;
234
                buff[off + n++] = slide[windowPos++] = slide[copyDist++];
235
            }
236
237
            if(n == size) return size;
238
        }
239
240
        method = -1; // done
241
        return n;
242
    }
243
244
    function stored(buff, off, size) {
245
        cutBits(bitLen & 7);
246
        var n = maskBits(0x10);
247
        if(n != ((~maskBits(0x10)) & 0xffff)) return -1;
248
        copyLen = n;
249
250
        n = 0;
251
        while(copyLen > 0 && n < size) {
0 ignored issues
show
Bug introduced by
The variable copyLen is changed as part of the while loop for example by copyLen-- on line 252. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
252
            copyLen--;
253
            windowPos &= WSIZE - 1;
0 ignored issues
show
Bug introduced by
The variable windowPos is changed as part of the while loop for example by windowPos++ on line 254. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
254
            buff[off + n++] = slide[windowPos++] = maskBits(8);
255
        }
256
257
        if(copyLen == 0) method = -1;
258
        return n;
259
    }
260
261
    function fixed(buff, off, size) {
262
        var fixed_bd = 0;
263
        if(fixedTableList == null) {
264
            var lengths = [];
265
266
            for(var symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8;
267
            for(; symbol < 256; symbol++) lengths[symbol] = 9;
268
            for(; symbol < 280; symbol++) lengths[symbol] = 7;
269
            for(; symbol < 288; symbol++) lengths[symbol] = 8;
270
271
            fixedLookup = 7;
272
273
            var htbl = new HuffTable(lengths, 288, 257, LENS, LEXT, fixedLookup);
274
275
            if(htbl.status != 0) return -1;
276
277
            fixedTableList = htbl.root;
278
            fixedLookup = htbl.maxbit;
279
280
            for(symbol = 0; symbol < 30; symbol++) lengths[symbol] = 5;
281
            fixed_bd = 5;
282
283
            htbl = new HuffTable(lengths, 30, 0, DISTS, DEXT, fixed_bd);
284
            if(htbl.status > 1) {
285
                fixedTableList = null;
286
                return -1;
287
            }
288
            fixedTableDist = htbl.root;
289
            fixed_bd = htbl.maxbit;
290
        }
291
292
        tblList = fixedTableList;
293
        tblDist = fixedTableDist;
0 ignored issues
show
Bug introduced by
The variable fixedTableDist does not seem to be initialized in case fixedTableList == null on line 263 is false. Are you sure this can never be the case?
Loading history...
294
        bitList = fixedLookup;
0 ignored issues
show
Bug introduced by
The variable fixedLookup does not seem to be initialized in case fixedTableList == null on line 263 is false. Are you sure this can never be the case?
Loading history...
295
        bitdist = fixed_bd;
296
        return codes(buff, off, size);
297
    }
298
299
    function dynamic(buff, off, size) {
300
        var ll = new Array(0x023C);
301
302
        for (var m = 0; m < 0x023C; m++) ll[m] = 0;
303
304
        var llencnt = 257 + maskBits(5),
305
            dcodescnt = 1 + maskBits(5),
306
            bitlencnt = 4 + maskBits(4);
307
308
        if(llencnt > 286 || dcodescnt > 30) return -1;
309
310
        for(var j = 0; j < bitlencnt; j++) ll[BITORDER[j]] = maskBits(3);
311
        for(; j < 19; j++) ll[BITORDER[j]] = 0;
312
313
        // build decoding table for trees--single level, 7 bit lookup
314
        bitList = 7;
315
        var hufTable = new HuffTable(ll, 19, 19, null, null, bitList);
316
        if(hufTable.status != 0)
317
            return -1;	// incomplete code set
318
319
        tblList = hufTable.root;
320
        bitList = hufTable.maxbit;
321
        var lencnt = llencnt + dcodescnt,
322
            i = 0,
323
            lastLen = 0;
324
        while(i < lencnt) {
325
            var hufLcode = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
326
            j = hufLcode.bitcnt;
327
            cutBits(j);
328
            j = hufLcode.lbase;
329
            if(j < 16)
330
                ll[i++] = lastLen = j;
331
            else if(j == 16) {
332
                j = 3 + maskBits(2);
333
                if(i + j > lencnt) return -1;
334
                while(j-- > 0) ll[i++] = lastLen;
335
            } else if(j == 17) {
336
                j = 3 + maskBits(3);
337
                if(i + j > lencnt) return -1;
338
                while(j-- > 0) ll[i++] = 0;
339
                lastLen = 0;
340
            } else {
341
                j = 11 + maskBits(7);
342
                if(i + j > lencnt) return -1;
343
                while(j-- > 0) ll[i++] = 0;
344
                lastLen = 0;
345
            }
346
        }
347
        bitList = 9;
348
        hufTable = new HuffTable(ll, llencnt, 257, LENS, LEXT, bitList);
349
        bitList == 0 && (hufTable.status = 1);
350
351
        if (hufTable.status != 0) return -1;
352
353
        tblList = hufTable.root;
354
        bitList = hufTable.maxbit;
355
356
        for(i = 0; i < dcodescnt; i++) ll[i] = ll[i + llencnt];
357
        bitdist = 6;
358
        hufTable = new HuffTable(ll, dcodescnt, 0, DISTS, DEXT, bitdist);
359
        tblDist = hufTable.root;
360
        bitdist = hufTable.maxbit;
361
362
        if((bitdist == 0 && llencnt > 257) || hufTable.status != 0) return -1;
363
364
        return codes(buff, off, size);
365
    }
366
367
    return {
368
        inflate : function(/*Buffer*/outputBuffer) {
369
            tblList = null;
370
371
            var size = outputBuffer.length,
372
                offset = 0, i;
373
374
            while(offset < size) {
375
                if(eof && method == -1) return;
0 ignored issues
show
Bug introduced by
The variable method is changed as part of the while loop for example by maskBits(2) on line 398. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable eof is changed as part of the while loop for example by maskBits(1) != 0 on line 397. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
376
                if(copyLen > 0) {
0 ignored issues
show
Bug introduced by
The variable copyLen is changed as part of the while loop for example by 0 on line 400. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
377
                    if(method != 0) {
378
                        while(copyLen > 0 && offset < size) {
379
                            copyLen--;
380
                            copyDist &= WSIZE - 1;
0 ignored issues
show
Bug introduced by
The variable copyDist is changed as part of the while loop for example by copyDist++ on line 382. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
381
                            windowPos &= WSIZE - 1;
0 ignored issues
show
Bug introduced by
The variable windowPos is changed as part of the while loop for example by windowPos++ on line 382. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
382
                            outputBuffer[offset++] = (slide[windowPos++] = slide[copyDist++]);
383
                        }
384
                    } else {
385
                        while(copyLen > 0 && offset < size) {
386
                            copyLen--;
387
                            windowPos &= WSIZE - 1;
388
                            outputBuffer[offset++] = (slide[windowPos++] = maskBits(8));
389
                        }
390
                        copyLen == 0 && (method = -1); // done
391
                    }
392
                    if (offset == size) return;
393
                }
394
395
                if(method == -1) {
396
                    if(eof) break;
397
                    eof = maskBits(1) != 0;
398
                    method = maskBits(2);
399
                    tblList = null;
400
                    copyLen = 0;
401
                }
402
                switch(method) {
403
                    case 0: i = stored(outputBuffer, offset, size - offset); break;
404
                    case 1: i = tblList != null ? codes(outputBuffer, offset, size - offset) : fixed(outputBuffer, offset, size - offset); break;
0 ignored issues
show
Bug introduced by
The variable tblList is changed as part of the while loop for example by null on line 399. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
405
                    case 2: i = tblList != null ? codes(outputBuffer, offset, size - offset) : dynamic(outputBuffer, offset, size - offset); break;
406
                    default: i = -1; break;
407
                }
408
409
                if(i == -1) return;
410
                offset += i;
411
            }
412
        }
413
    };
414
}
415
416
module.exports = function(/*Buffer*/inbuf) {
417
    var zlib = require("zlib");
418
    return {
419
        inflateAsync : function(/*Function*/callback) {
420
            var tmp = zlib.createInflateRaw(),
421
                parts = [], total = 0;
422
            tmp.on('data', function(data) {
423
                parts.push(data);
424
                total += data.length;
425
            });
426
            tmp.on('end', function() {
427
                var buf = new Buffer(total), written = 0;
428
                buf.fill(0);
429
430
                for (var i = 0; i < parts.length; i++) {
431
                    var part = parts[i];
432
                    part.copy(buf, written);
433
                    written += part.length;
434
                }
435
                callback && callback(buf);
436
            });
437
            tmp.end(inbuf)
438
        },
439
440
        inflate : function(/*Buffer*/outputBuffer) {
441
            var x = {
442
                x: new JSInflater(inbuf)
443
            };
444
            x.x.inflate(outputBuffer);
445
            delete(x.x);
446
        }
447
    }
448
};
449