~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/util/zip/DeflaterEngine.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* DeflaterEngine.java --
 
2
   Copyright (C) 2001, 2004, 2005  Free Software Foundation, Inc.
 
3
 
 
4
This file is part of GNU Classpath.
 
5
 
 
6
GNU Classpath is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; either version 2, or (at your option)
 
9
any later version.
 
10
 
 
11
GNU Classpath is distributed in the hope that it will be useful, but
 
12
WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with GNU Classpath; see the file COPYING.  If not, write to the
 
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
19
02110-1301 USA.
 
20
 
 
21
Linking this library statically or dynamically with other modules is
 
22
making a combined work based on this library.  Thus, the terms and
 
23
conditions of the GNU General Public License cover the whole
 
24
combination.
 
25
 
 
26
As a special exception, the copyright holders of this library give you
 
27
permission to link this library with independent modules to produce an
 
28
executable, regardless of the license terms of these independent
 
29
modules, and to copy and distribute the resulting executable under
 
30
terms of your choice, provided that you also meet, for each linked
 
31
independent module, the terms and conditions of the license of that
 
32
module.  An independent module is a module which is not derived from
 
33
or based on this library.  If you modify this library, you may extend
 
34
this exception to your version of the library, but you are not
 
35
obligated to do so.  If you do not wish to do so, delete this
 
36
exception statement from your version. */
 
37
 
 
38
package java.util.zip;
 
39
 
 
40
final class DeflaterEngine implements DeflaterConstants
 
41
{
 
42
  private static final int TOO_FAR = 4096;
 
43
 
 
44
  private int ins_h;
 
45
 
 
46
  /**
 
47
   * Hashtable, hashing three characters to an index for window, so
 
48
   * that window[index]..window[index+2] have this hash code.  
 
49
   * Note that the array should really be unsigned short, so you need
 
50
   * to and the values with 0xffff.
 
51
   */
 
52
  private short[] head;
 
53
 
 
54
  /**
 
55
   * prev[index & WMASK] points to the previous index that has the
 
56
   * same hash code as the string starting at index.  This way 
 
57
   * entries with the same hash code are in a linked list.
 
58
   * Note that the array should really be unsigned short, so you need
 
59
   * to and the values with 0xffff.
 
60
   */
 
61
  private short[] prev;
 
62
 
 
63
  private int matchStart, matchLen;
 
64
  private boolean prevAvailable;
 
65
  private int blockStart;
 
66
 
 
67
  /**
 
68
   * strstart points to the current character in window.
 
69
   */
 
70
  private int strstart;
 
71
 
 
72
  /**
 
73
   * lookahead is the number of characters starting at strstart in
 
74
   * window that are valid.
 
75
   * So window[strstart] until window[strstart+lookahead-1] are valid
 
76
   * characters.
 
77
   */
 
78
  private int lookahead;
 
79
 
 
80
  /**
 
81
   * This array contains the part of the uncompressed stream that 
 
82
   * is of relevance.  The current character is indexed by strstart.
 
83
   */
 
84
  private byte[] window;
 
85
 
 
86
  private int strategy, max_chain, max_lazy, niceLength, goodLength;
 
87
 
 
88
  /** The current compression function. */
 
89
  private int comprFunc;
 
90
 
 
91
  /** The input data for compression. */
 
92
  private byte[] inputBuf;
 
93
 
 
94
  /** The total bytes of input read. */
 
95
  private long totalIn;
 
96
 
 
97
  /** The offset into inputBuf, where input data starts. */
 
98
  private int inputOff;
 
99
 
 
100
  /** The end offset of the input data. */
 
101
  private int inputEnd;
 
102
 
 
103
  private DeflaterPending pending;
 
104
  private DeflaterHuffman huffman;
 
105
 
 
106
  /** The adler checksum */
 
107
  private Adler32 adler;
 
108
 
 
109
  /* DEFLATE ALGORITHM:
 
110
   *
 
111
   * The uncompressed stream is inserted into the window array.  When
 
112
   * the window array is full the first half is thrown away and the
 
113
   * second half is copied to the beginning.
 
114
   *
 
115
   * The head array is a hash table.  Three characters build a hash value
 
116
   * and they the value points to the corresponding index in window of 
 
117
   * the last string with this hash.  The prev array implements a
 
118
   * linked list of matches with the same hash: prev[index & WMASK] points
 
119
   * to the previous index with the same hash.
 
120
   * 
 
121
   * 
 
122
   */
 
123
 
 
124
 
 
125
  DeflaterEngine(DeflaterPending pending) {
 
126
    this.pending = pending;
 
127
    huffman = new DeflaterHuffman(pending);
 
128
    adler = new Adler32();
 
129
 
 
130
    window = new byte[2*WSIZE];
 
131
    head   = new short[HASH_SIZE];
 
132
    prev   = new short[WSIZE];
 
133
 
 
134
    /* We start at index 1, to avoid a implementation deficiency, that
 
135
     * we cannot build a repeat pattern at index 0.
 
136
     */
 
137
    blockStart = strstart = 1;
 
138
  }
 
139
 
 
140
  public void reset()
 
141
  {
 
142
    huffman.reset();
 
143
    adler.reset();
 
144
    clearHash();
 
145
    totalIn = 0;
 
146
  }
 
147
  
 
148
  final void clearHash()
 
149
  {
 
150
    blockStart = strstart = 1;
 
151
    lookahead = 0;
 
152
    prevAvailable = false;
 
153
    matchLen = MIN_MATCH - 1;
 
154
    for (int i = 0; i < HASH_SIZE; i++)
 
155
      head[i] = 0;
 
156
    for (int i = 0; i < WSIZE; i++)
 
157
      prev[i] = 0;
 
158
  }
 
159
 
 
160
  public final void resetAdler()
 
161
  {
 
162
    adler.reset();
 
163
  }
 
164
 
 
165
  public final int getAdler()
 
166
  {
 
167
    int chksum = (int) adler.getValue();
 
168
    return chksum;
 
169
  }
 
170
 
 
171
  public final long getTotalIn()
 
172
  {
 
173
    return totalIn;
 
174
  }
 
175
 
 
176
  public final void setStrategy(int strat)
 
177
  {
 
178
    strategy = strat;
 
179
  }
 
180
 
 
181
  public void setLevel(int lvl)
 
182
  {
 
183
    goodLength = DeflaterConstants.GOOD_LENGTH[lvl];
 
184
    max_lazy    = DeflaterConstants.MAX_LAZY[lvl];
 
185
    niceLength = DeflaterConstants.NICE_LENGTH[lvl];
 
186
    max_chain   = DeflaterConstants.MAX_CHAIN[lvl];
 
187
 
 
188
    if (DeflaterConstants.COMPR_FUNC[lvl] != comprFunc) 
 
189
      {
 
190
        if (DeflaterConstants.DEBUGGING)
 
191
          System.err.println("Change from "+comprFunc +" to "
 
192
                             + DeflaterConstants.COMPR_FUNC[lvl]);
 
193
        switch (comprFunc)
 
194
          {
 
195
          case DEFLATE_STORED:
 
196
            if (strstart > blockStart)
 
197
              {
 
198
                huffman.flushStoredBlock(window, blockStart, 
 
199
                                         strstart - blockStart, false);
 
200
                blockStart = strstart;
 
201
              }
 
202
            updateHash();
 
203
            break;
 
204
          case DEFLATE_FAST:
 
205
            if (strstart > blockStart)
 
206
              {
 
207
                huffman.flushBlock(window, blockStart, strstart - blockStart,
 
208
                                   false);
 
209
                blockStart = strstart;
 
210
              }
 
211
            break;
 
212
          case DEFLATE_SLOW:
 
213
            if (prevAvailable)
 
214
              huffman.tallyLit(window[strstart-1] & 0xff);
 
215
            if (strstart > blockStart)
 
216
              {
 
217
                huffman.flushBlock(window, blockStart, strstart - blockStart,
 
218
                                   false);
 
219
                blockStart = strstart;
 
220
              }
 
221
            prevAvailable = false;
 
222
            matchLen = MIN_MATCH - 1;
 
223
            break;
 
224
          }
 
225
        comprFunc = COMPR_FUNC[lvl];
 
226
      }
 
227
  }
 
228
 
 
229
  private void updateHash() {
 
230
    if (DEBUGGING)
 
231
      System.err.println("updateHash: "+strstart);
 
232
    ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1];
 
233
  }    
 
234
 
 
235
  /**
 
236
   * Inserts the current string in the head hash and returns the previous
 
237
   * value for this hash.
 
238
   */
 
239
  private int insertString() {
 
240
    short match;
 
241
    int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)])
 
242
      & HASH_MASK;
 
243
 
 
244
    if (DEBUGGING)
 
245
      {
 
246
        if (hash != (((window[strstart] << (2*HASH_SHIFT))
 
247
                      ^ (window[strstart + 1] << HASH_SHIFT)
 
248
                      ^ (window[strstart + 2])) & HASH_MASK))
 
249
          throw new InternalError("hash inconsistent: "+hash+"/"
 
250
                                  +window[strstart]+","
 
251
                                  +window[strstart+1]+","
 
252
                                  +window[strstart+2]+","+HASH_SHIFT);
 
253
      }
 
254
 
 
255
    prev[strstart & WMASK] = match = head[hash];
 
256
    head[hash] = (short) strstart;
 
257
    ins_h = hash;
 
258
    return match & 0xffff;
 
259
  }
 
260
 
 
261
  private void slideWindow()
 
262
  {
 
263
    System.arraycopy(window, WSIZE, window, 0, WSIZE);
 
264
    matchStart -= WSIZE;
 
265
    strstart -= WSIZE;
 
266
    blockStart -= WSIZE;
 
267
    
 
268
    /* Slide the hash table (could be avoided with 32 bit values
 
269
     * at the expense of memory usage).
 
270
     */
 
271
    for (int i = 0; i < HASH_SIZE; i++) 
 
272
      {
 
273
        int m = head[i] & 0xffff;
 
274
        head[i] = m >= WSIZE ? (short) (m - WSIZE) : 0;
 
275
      }
 
276
 
 
277
    /* Slide the prev table.
 
278
     */
 
279
    for (int i = 0; i < WSIZE; i++) 
 
280
      {
 
281
        int m = prev[i] & 0xffff;
 
282
        prev[i] = m >= WSIZE ? (short) (m - WSIZE) : 0;
 
283
      }
 
284
  }
 
285
 
 
286
  /**
 
287
   * Fill the window when the lookahead becomes insufficient.
 
288
   * Updates strstart and lookahead.
 
289
   *
 
290
   * OUT assertions: strstart + lookahead <= 2*WSIZE
 
291
   *    lookahead >= MIN_LOOKAHEAD or inputOff == inputEnd
 
292
   */
 
293
  private void fillWindow()
 
294
  {
 
295
    /* If the window is almost full and there is insufficient lookahead,
 
296
     * move the upper half to the lower one to make room in the upper half.
 
297
     */
 
298
    if (strstart >= WSIZE + MAX_DIST)
 
299
      slideWindow();
 
300
 
 
301
    /* If there is not enough lookahead, but still some input left,
 
302
     * read in the input
 
303
     */
 
304
    while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd)
 
305
      {
 
306
        int more = 2*WSIZE - lookahead - strstart;
 
307
        
 
308
        if (more > inputEnd - inputOff)
 
309
          more = inputEnd - inputOff;
 
310
 
 
311
        System.arraycopy(inputBuf, inputOff, 
 
312
                         window, strstart + lookahead, more);
 
313
        adler.update(inputBuf, inputOff, more);
 
314
        inputOff += more;
 
315
        totalIn  += more;
 
316
        lookahead += more;
 
317
      }
 
318
 
 
319
    if (lookahead >= MIN_MATCH) 
 
320
      updateHash();
 
321
  }
 
322
 
 
323
  /**
 
324
   * Find the best (longest) string in the window matching the 
 
325
   * string starting at strstart.
 
326
   *
 
327
   * Preconditions:
 
328
   *    strstart + MAX_MATCH <= window.length.
 
329
   *    
 
330
   *
 
331
   * @param curMatch
 
332
   */
 
333
  private boolean findLongestMatch(int curMatch) {
 
334
    int chainLength = this.max_chain;
 
335
    int niceLength = this.niceLength;
 
336
    short[] prev = this.prev;
 
337
    int scan  = this.strstart;
 
338
    int match;
 
339
    int best_end = this.strstart + matchLen;
 
340
    int best_len = Math.max(matchLen, MIN_MATCH - 1);
 
341
    
 
342
    int limit = Math.max(strstart - MAX_DIST, 0);
 
343
 
 
344
    int strend = scan + MAX_MATCH - 1;
 
345
    byte scan_end1 = window[best_end - 1];
 
346
    byte scan_end  = window[best_end];
 
347
 
 
348
    /* Do not waste too much time if we already have a good match: */
 
349
    if (best_len >= this.goodLength)
 
350
      chainLength >>= 2;
 
351
 
 
352
    /* Do not look for matches beyond the end of the input. This is necessary
 
353
     * to make deflate deterministic.
 
354
     */
 
355
    if (niceLength > lookahead)
 
356
      niceLength = lookahead;
 
357
 
 
358
    if (DeflaterConstants.DEBUGGING 
 
359
        && strstart > 2*WSIZE - MIN_LOOKAHEAD)
 
360
      throw new InternalError("need lookahead");
 
361
    
 
362
    do {
 
363
      if (DeflaterConstants.DEBUGGING && curMatch >= strstart)
 
364
        throw new InternalError("future match");
 
365
      if (window[curMatch + best_len] != scan_end
 
366
          || window[curMatch + best_len - 1] != scan_end1
 
367
          || window[curMatch] != window[scan]
 
368
          || window[curMatch+1] != window[scan + 1])
 
369
        continue;
 
370
 
 
371
      match = curMatch + 2;      
 
372
      scan += 2;
 
373
 
 
374
      /* We check for insufficient lookahead only every 8th comparison;
 
375
       * the 256th check will be made at strstart+258.
 
376
       */
 
377
      while (window[++scan] == window[++match]
 
378
             && window[++scan] == window[++match]
 
379
             && window[++scan] == window[++match]
 
380
             && window[++scan] == window[++match]
 
381
             && window[++scan] == window[++match]
 
382
             && window[++scan] == window[++match]
 
383
             && window[++scan] == window[++match]
 
384
             && window[++scan] == window[++match]
 
385
             && scan < strend)
 
386
        ;
 
387
 
 
388
      if (scan > best_end) {
 
389
//      if (DeflaterConstants.DEBUGGING && ins_h == 0)
 
390
//        System.err.println("Found match: "+curMatch+"-"+(scan-strstart));
 
391
        matchStart = curMatch;
 
392
        best_end = scan;
 
393
        best_len = scan - strstart;
 
394
        if (best_len >= niceLength)
 
395
          break;
 
396
 
 
397
        scan_end1  = window[best_end-1];
 
398
        scan_end   = window[best_end];
 
399
      }
 
400
      scan = strstart;
 
401
    } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit
 
402
             && --chainLength != 0);
 
403
 
 
404
    matchLen = Math.min(best_len, lookahead);
 
405
    return matchLen >= MIN_MATCH;
 
406
  }
 
407
 
 
408
  void setDictionary(byte[] buffer, int offset, int length) {
 
409
    if (DeflaterConstants.DEBUGGING && strstart != 1)
 
410
      throw new IllegalStateException("strstart not 1");
 
411
    adler.update(buffer, offset, length);
 
412
    if (length < MIN_MATCH)
 
413
      return;
 
414
    if (length > MAX_DIST) {
 
415
      offset += length - MAX_DIST;
 
416
      length = MAX_DIST;
 
417
    }
 
418
 
 
419
    System.arraycopy(buffer, offset, window, strstart, length);
 
420
 
 
421
    updateHash();
 
422
    length--;
 
423
    while (--length > 0)
 
424
      {
 
425
        insertString();
 
426
        strstart++;
 
427
      }
 
428
    strstart += 2;
 
429
    blockStart = strstart;
 
430
  }    
 
431
    
 
432
  private boolean deflateStored(boolean flush, boolean finish)
 
433
  {
 
434
    if (!flush && lookahead == 0)
 
435
      return false;
 
436
 
 
437
    strstart += lookahead;
 
438
    lookahead = 0;
 
439
 
 
440
    int storedLen = strstart - blockStart;
 
441
 
 
442
    if ((storedLen >= DeflaterConstants.MAX_BLOCK_SIZE) 
 
443
        /* Block is full */
 
444
        || (blockStart < WSIZE && storedLen >= MAX_DIST)
 
445
        /* Block may move out of window */
 
446
        || flush)
 
447
      {
 
448
        boolean lastBlock = finish;
 
449
        if (storedLen > DeflaterConstants.MAX_BLOCK_SIZE)
 
450
          {
 
451
            storedLen = DeflaterConstants.MAX_BLOCK_SIZE;
 
452
            lastBlock = false;
 
453
          }
 
454
 
 
455
        if (DeflaterConstants.DEBUGGING)
 
456
          System.err.println("storedBlock["+storedLen+","+lastBlock+"]");
 
457
 
 
458
        huffman.flushStoredBlock(window, blockStart, storedLen, lastBlock);
 
459
        blockStart += storedLen;
 
460
        return !lastBlock;
 
461
      }
 
462
    return true;
 
463
  }
 
464
 
 
465
  private boolean deflateFast(boolean flush, boolean finish)
 
466
  {
 
467
    if (lookahead < MIN_LOOKAHEAD && !flush)
 
468
      return false;
 
469
 
 
470
    while (lookahead >= MIN_LOOKAHEAD || flush)
 
471
      {
 
472
        if (lookahead == 0)
 
473
          {
 
474
            /* We are flushing everything */
 
475
            huffman.flushBlock(window, blockStart, strstart - blockStart,
 
476
                               finish);
 
477
            blockStart = strstart;
 
478
            return false;
 
479
          }
 
480
 
 
481
        if (strstart > 2 * WSIZE - MIN_LOOKAHEAD)
 
482
          {
 
483
            /* slide window, as findLongestMatch need this.
 
484
             * This should only happen when flushing and the window
 
485
             * is almost full.
 
486
             */
 
487
            slideWindow();
 
488
          }
 
489
 
 
490
        int hashHead;
 
491
        if (lookahead >= MIN_MATCH 
 
492
            && (hashHead = insertString()) != 0
 
493
            && strategy != Deflater.HUFFMAN_ONLY
 
494
            && strstart - hashHead <= MAX_DIST
 
495
            && findLongestMatch(hashHead))
 
496
          {
 
497
            /* longestMatch sets matchStart and matchLen */
 
498
            if (DeflaterConstants.DEBUGGING)
 
499
              {
 
500
                for (int i = 0 ; i < matchLen; i++)
 
501
                  {
 
502
                    if (window[strstart+i] != window[matchStart + i])
 
503
                      throw new InternalError();
 
504
                  }
 
505
              }
 
506
            boolean full = huffman.tallyDist(strstart - matchStart, matchLen);
 
507
            
 
508
            lookahead -= matchLen;
 
509
            if (matchLen <= max_lazy && lookahead >= MIN_MATCH)
 
510
              {
 
511
                while (--matchLen > 0)
 
512
                  {
 
513
                    strstart++;
 
514
                    insertString();
 
515
                  }
 
516
                strstart++;
 
517
              }
 
518
            else
 
519
              {
 
520
                strstart += matchLen;
 
521
                if (lookahead >= MIN_MATCH - 1)
 
522
                  updateHash();
 
523
              }
 
524
            matchLen = MIN_MATCH - 1;
 
525
            if (!full)
 
526
              continue;
 
527
          }
 
528
        else
 
529
          {
 
530
            /* No match found */
 
531
            huffman.tallyLit(window[strstart] & 0xff);
 
532
            strstart++;
 
533
            lookahead--;
 
534
          }
 
535
 
 
536
        if (huffman.isFull())
 
537
          {
 
538
            boolean lastBlock = finish && lookahead == 0;
 
539
            huffman.flushBlock(window, blockStart, strstart - blockStart,
 
540
                               lastBlock);
 
541
            blockStart = strstart;
 
542
            return !lastBlock;
 
543
          }
 
544
      }
 
545
    return true;
 
546
  }
 
547
 
 
548
  private boolean deflateSlow(boolean flush, boolean finish)
 
549
  {
 
550
    if (lookahead < MIN_LOOKAHEAD && !flush)
 
551
      return false;
 
552
 
 
553
    while (lookahead >= MIN_LOOKAHEAD || flush)
 
554
      {
 
555
        if (lookahead == 0)
 
556
          {
 
557
            if (prevAvailable)
 
558
              huffman.tallyLit(window[strstart-1] & 0xff);
 
559
            prevAvailable = false;
 
560
 
 
561
            /* We are flushing everything */
 
562
            if (DeflaterConstants.DEBUGGING && !flush)
 
563
              throw new InternalError("Not flushing, but no lookahead");
 
564
            huffman.flushBlock(window, blockStart, strstart - blockStart,
 
565
                               finish);
 
566
            blockStart = strstart;
 
567
            return false;
 
568
          }
 
569
 
 
570
        if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD)
 
571
          {
 
572
            /* slide window, as findLongestMatch need this.
 
573
             * This should only happen when flushing and the window
 
574
             * is almost full.
 
575
             */
 
576
            slideWindow();
 
577
          }
 
578
 
 
579
        int prevMatch = matchStart;
 
580
        int prevLen = matchLen;
 
581
        if (lookahead >= MIN_MATCH)
 
582
          {
 
583
            int hashHead = insertString();
 
584
            if (strategy != Deflater.HUFFMAN_ONLY
 
585
                && hashHead != 0 && strstart - hashHead <= MAX_DIST
 
586
                && findLongestMatch(hashHead))
 
587
              {
 
588
                /* longestMatch sets matchStart and matchLen */
 
589
                
 
590
                /* Discard match if too small and too far away */
 
591
                if (matchLen <= 5
 
592
                    && (strategy == Deflater.FILTERED
 
593
                        || (matchLen == MIN_MATCH
 
594
                            && strstart - matchStart > TOO_FAR))) {
 
595
                  matchLen = MIN_MATCH - 1;
 
596
                }
 
597
              }
 
598
          }
 
599
        
 
600
        /* previous match was better */
 
601
        if (prevLen >= MIN_MATCH && matchLen <= prevLen)
 
602
          {
 
603
            if (DeflaterConstants.DEBUGGING)
 
604
              {
 
605
                for (int i = 0 ; i < matchLen; i++)
 
606
                  {
 
607
                    if (window[strstart-1+i] != window[prevMatch + i])
 
608
                      throw new InternalError();
 
609
                  }
 
610
              }
 
611
            huffman.tallyDist(strstart - 1 - prevMatch, prevLen);
 
612
            prevLen -= 2;
 
613
            do 
 
614
              {
 
615
                strstart++;
 
616
                lookahead--;
 
617
                if (lookahead >= MIN_MATCH)
 
618
                  insertString();
 
619
              }
 
620
            while (--prevLen > 0);
 
621
            strstart ++;
 
622
            lookahead--;
 
623
            prevAvailable = false;
 
624
            matchLen = MIN_MATCH - 1;
 
625
          }
 
626
        else
 
627
          {
 
628
            if (prevAvailable)
 
629
              huffman.tallyLit(window[strstart-1] & 0xff);
 
630
            prevAvailable = true;
 
631
            strstart++;
 
632
            lookahead--;
 
633
          }
 
634
 
 
635
        if (huffman.isFull())
 
636
          {
 
637
            int len = strstart - blockStart;
 
638
            if (prevAvailable)
 
639
              len--;
 
640
            boolean lastBlock = (finish && lookahead == 0 && !prevAvailable);
 
641
            huffman.flushBlock(window, blockStart, len, lastBlock);
 
642
            blockStart += len;
 
643
            return !lastBlock;
 
644
          }
 
645
      }
 
646
    return true;
 
647
  } 
 
648
 
 
649
  public boolean deflate(boolean flush, boolean finish) 
 
650
  {
 
651
    boolean progress;
 
652
    do
 
653
      {
 
654
        fillWindow();
 
655
        boolean canFlush = flush && inputOff == inputEnd;
 
656
        if (DeflaterConstants.DEBUGGING)
 
657
          System.err.println("window: ["+blockStart+","+strstart+","
 
658
                             +lookahead+"], "+comprFunc+","+canFlush);
 
659
        switch (comprFunc)
 
660
          {
 
661
          case DEFLATE_STORED:
 
662
            progress = deflateStored(canFlush, finish);
 
663
            break;
 
664
          case DEFLATE_FAST:
 
665
            progress = deflateFast(canFlush, finish);
 
666
            break;
 
667
          case DEFLATE_SLOW:
 
668
            progress = deflateSlow(canFlush, finish);
 
669
            break;
 
670
          default:
 
671
            throw new InternalError();
 
672
          }
 
673
      }
 
674
    while (pending.isFlushed()  /* repeat while we have no pending output */
 
675
           && progress);        /* and progress was made */
 
676
 
 
677
    return progress;
 
678
  }
 
679
 
 
680
  void setInput(byte[] buf, int off, int len)
 
681
  {
 
682
    // caller has already checked parameters
 
683
    inputBuf = buf;
 
684
    inputOff = off;
 
685
    inputEnd = off + len;
 
686
  }
 
687
 
 
688
  public final boolean needsInput()
 
689
  {
 
690
    return inputEnd == inputOff;
 
691
  }
 
692
}