View Javadoc

1   /*
2    * The Apache Software License, Version 1.1
3    *
4    * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
5    * reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions
9    * are met:
10   *
11   * 1. Redistributions of source code must retain the above copyright
12   *    notice, this list of conditions and the following disclaimer.
13   *
14   * 2. Redistributions in binary form must reproduce the above copyright
15   *    notice, this list of conditions and the following disclaimer in
16   *    the documentation and/or other materials provided with the
17   *    distribution.
18   *
19   * 3. The end-user documentation included with the redistribution, if
20   *    any, must include the following acknowlegement:
21   *       "This product includes software developed by the
22   *        Apache Software Foundation (http://www.apache.org/)."
23   *    Alternately, this acknowlegement may appear in the software itself,
24   *    if and wherever such third-party acknowlegements normally appear.
25   *
26   * 4. The names "Ant" and "Apache Software
27   *    Foundation" must not be used to endorse or promote products derived
28   *    from this software without prior written permission. For written
29   *    permission, please contact apache@apache.org.
30   *
31   * 5. Products derived from this software may not be called "Apache"
32   *    nor may "Apache" appear in their names without prior written
33   *    permission of the Apache Group.
34   *
35   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46   * SUCH DAMAGE.
47   * ====================================================================
48   *
49   * This software consists of voluntary contributions made by many
50   * individuals on behalf of the Apache Software Foundation.  For more
51   * information on the Apache Software Foundation, please see
52   * <http://www.apache.org/>.
53   */
54  
55  /*
56   * This package is based on the work done by Keiron Liddle, Aftex Software
57   * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
58   * great code.
59   */
60  
61  package com.jguild.jrpm.io.bzip2;
62  
63  import java.io.IOException;
64  import java.io.OutputStream;
65  
66  /***
67   * An output stream that compresses into the BZip2 format (without the file
68   * header chars) into another stream.
69   * 
70   * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
71   * 
72   * TODO: Update to BZip2 1.0.1
73   */
74  public class CBZip2OutputStream extends OutputStream implements BZip2Constants {
75      private static final int LOWER_BYTE_MASK = 0x000000ff;
76  
77      private static final int UPPER_BYTE_MASK = 0xffffff00;
78  
79      private static final int SETMASK = (1 << 21);
80  
81      private static final int CLEARMASK = (~SETMASK);
82  
83      private static final int GREATER_ICOST = 15;
84  
85      private static final int LESSER_ICOST = 0;
86  
87      private static final int SMALL_THRESH = 20;
88  
89      private static final int DEPTH_THRESH = 10;
90  
91      /*
92       * If you are ever unlucky/improbable enough to get a stack overflow whilst
93       * sorting, increase the following constant and try again. In practice I
94       * have never seen the stack go above 27 elems, so the following limit seems
95       * very generous.
96       */
97      private static final int QSORT_STACK_SIZE = 1000;
98  
99      private CRC m_crc = new CRC();
100 
101     private boolean[] m_inUse = new boolean[256];
102 
103     private char[] m_seqToUnseq = new char[256];
104 
105     private char[] m_unseqToSeq = new char[256];
106 
107     private char[] m_selector = new char[MAX_SELECTORS];
108 
109     private char[] m_selectorMtf = new char[MAX_SELECTORS];
110 
111     private int[] m_mtfFreq = new int[MAX_ALPHA_SIZE];
112 
113     private int m_currentChar = -1;
114 
115     private int m_runLength;
116 
117     private boolean m_closed;
118 
119     /*
120      * Knuth's increments seem to work better than Incerpi-Sedgewick here.
121      * Possibly because the number of elems to sort is usually small, typically <=
122      * 20.
123      */
124     private int[] m_incs = new int[] { 1, 4, 13, 40, 121, 364, 1093, 3280,
125             9841, 29524, 88573, 265720, 797161, 2391484 };
126 
127     private boolean m_blockRandomised;
128 
129     /*
130      * always: in the range 0 .. 9. The current block size is 100000 * this
131      * number.
132      */
133     private int m_blockSize100k;
134 
135     private int m_bsBuff;
136 
137     private int m_bsLive;
138 
139     /*
140      * index of the last char in the block, so the block size == last + 1.
141      */
142     private int m_last;
143 
144     /*
145      * index in zptr[] of original string after sorting.
146      */
147     private int m_origPtr;
148 
149     private int m_allowableBlockSize;
150 
151     private char[] m_block;
152 
153     private int m_blockCRC;
154 
155     private int m_combinedCRC;
156 
157     private OutputStream m_bsStream;
158 
159     private boolean m_firstAttempt;
160 
161     private int[] m_ftab;
162 
163     private int m_nInUse;
164 
165     private int m_nMTF;
166 
167     private int[] m_quadrant;
168 
169     private short[] m_szptr;
170 
171     private int m_workDone;
172 
173     /*
174      * Used when sorting. If too many long comparisons happen, we stop sorting,
175      * randomise the block slightly, and try again.
176      */
177     private int m_workFactor;
178 
179     private int m_workLimit;
180 
181     private int[] m_zptr;
182 
183     public CBZip2OutputStream(final OutputStream output) throws IOException {
184         this(output, 9);
185     }
186 
187     public CBZip2OutputStream(final OutputStream output, final int blockSize)
188             throws IOException {
189         bsSetStream(output);
190         m_workFactor = 50;
191 
192         int outBlockSize = blockSize;
193         if (outBlockSize > 9) {
194             outBlockSize = 9;
195         }
196         if (outBlockSize < 1) {
197             outBlockSize = 1;
198         }
199         m_blockSize100k = outBlockSize;
200         allocateCompressStructures();
201         initialize();
202         initBlock();
203     }
204 
205     private static void hbMakeCodeLengths(char[] len, int[] freq,
206             int alphaSize, int maxLen) {
207         /*
208          * Nodes and heap entries run from 1. Entry 0 for both the heap and
209          * nodes is a sentinel.
210          */
211         int nNodes;
212         /*
213          * Nodes and heap entries run from 1. Entry 0 for both the heap and
214          * nodes is a sentinel.
215          */
216         int nHeap;
217         /*
218          * Nodes and heap entries run from 1. Entry 0 for both the heap and
219          * nodes is a sentinel.
220          */
221         int n1;
222         /*
223          * Nodes and heap entries run from 1. Entry 0 for both the heap and
224          * nodes is a sentinel.
225          */
226         int n2;
227         /*
228          * Nodes and heap entries run from 1. Entry 0 for both the heap and
229          * nodes is a sentinel.
230          */
231         int i;
232         /*
233          * Nodes and heap entries run from 1. Entry 0 for both the heap and
234          * nodes is a sentinel.
235          */
236         int j;
237         /*
238          * Nodes and heap entries run from 1. Entry 0 for both the heap and
239          * nodes is a sentinel.
240          */
241         int k;
242         boolean tooLong;
243 
244         int[] heap = new int[MAX_ALPHA_SIZE + 2];
245         int[] weights = new int[MAX_ALPHA_SIZE * 2];
246         int[] parent = new int[MAX_ALPHA_SIZE * 2];
247 
248         for (i = 0; i < alphaSize; i++) {
249             weights[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
250         }
251 
252         while (true) {
253             nNodes = alphaSize;
254             nHeap = 0;
255 
256             heap[0] = 0;
257             weights[0] = 0;
258             parent[0] = -2;
259 
260             for (i = 1; i <= alphaSize; i++) {
261                 parent[i] = -1;
262                 nHeap++;
263                 heap[nHeap] = i;
264                 {
265                     int zz;
266                     int tmp;
267                     zz = nHeap;
268                     tmp = heap[zz];
269                     while (weights[tmp] < weights[heap[zz >> 1]]) {
270                         heap[zz] = heap[zz >> 1];
271                         zz >>= 1;
272                     }
273                     heap[zz] = tmp;
274                 }
275             }
276             if (!(nHeap < (MAX_ALPHA_SIZE + 2))) {
277                 panic();
278             }
279 
280             while (nHeap > 1) {
281                 n1 = heap[1];
282                 heap[1] = heap[nHeap];
283                 nHeap--;
284                 {
285                     int zz = 0;
286                     int yy = 0;
287                     int tmp = 0;
288                     zz = 1;
289                     tmp = heap[zz];
290                     while (true) {
291                         yy = zz << 1;
292                         if (yy > nHeap) {
293                             break;
294                         }
295                         if (yy < nHeap
296                                 && weights[heap[yy + 1]] < weights[heap[yy]]) {
297                             yy++;
298                         }
299                         if (weights[tmp] < weights[heap[yy]]) {
300                             break;
301                         }
302                         heap[zz] = heap[yy];
303                         zz = yy;
304                     }
305                     heap[zz] = tmp;
306                 }
307                 n2 = heap[1];
308                 heap[1] = heap[nHeap];
309                 nHeap--;
310                 {
311                     int zz = 0;
312                     int yy = 0;
313                     int tmp = 0;
314                     zz = 1;
315                     tmp = heap[zz];
316                     while (true) {
317                         yy = zz << 1;
318                         if (yy > nHeap) {
319                             break;
320                         }
321                         if (yy < nHeap
322                                 && weights[heap[yy + 1]] < weights[heap[yy]]) {
323                             yy++;
324                         }
325                         if (weights[tmp] < weights[heap[yy]]) {
326                             break;
327                         }
328                         heap[zz] = heap[yy];
329                         zz = yy;
330                     }
331                     heap[zz] = tmp;
332                 }
333                 nNodes++;
334                 parent[n1] = nNodes;
335                 parent[n2] = nNodes;
336 
337                 final int v1 = weights[n1];
338                 final int v2 = weights[n2];
339                 final int weight = calculateWeight(v1, v2);
340                 weights[nNodes] = weight;
341 
342                 parent[nNodes] = -1;
343                 nHeap++;
344                 heap[nHeap] = nNodes;
345                 {
346                     int zz = 0;
347                     int tmp = 0;
348                     zz = nHeap;
349                     tmp = heap[zz];
350                     while (weights[tmp] < weights[heap[zz >> 1]]) {
351                         heap[zz] = heap[zz >> 1];
352                         zz >>= 1;
353                     }
354                     heap[zz] = tmp;
355                 }
356             }
357             if (!(nNodes < (MAX_ALPHA_SIZE * 2))) {
358                 panic();
359             }
360 
361             tooLong = false;
362             for (i = 1; i <= alphaSize; i++) {
363                 j = 0;
364                 k = i;
365                 while (parent[k] >= 0) {
366                     k = parent[k];
367                     j++;
368                 }
369                 len[i - 1] = (char) j;
370                 if (j > maxLen) {
371                     tooLong = true;
372                 }
373             }
374 
375             if (!tooLong) {
376                 break;
377             }
378 
379             for (i = 1; i < alphaSize; i++) {
380                 j = weights[i] >> 8;
381                 j = 1 + (j / 2);
382                 weights[i] = j << 8;
383             }
384         }
385     }
386 
387     private static int calculateWeight(final int v1, final int v2) {
388         final int upper = (v1 & UPPER_BYTE_MASK) + (v2 & UPPER_BYTE_MASK);
389         final int v1Lower = (v1 & LOWER_BYTE_MASK);
390         final int v2Lower = (v2 & LOWER_BYTE_MASK);
391         final int nnnn = (v1Lower > v2Lower) ? v1Lower : v2Lower;
392         return upper | (1 + nnnn);
393     }
394 
395     private static void panic() {
396         System.out.println("panic");
397         // throw new CError();
398     }
399 
400     public void close() throws IOException {
401         if (m_closed) {
402             return;
403         }
404 
405         if (m_runLength > 0) {
406             writeRun();
407         }
408         m_currentChar = -1;
409         endBlock();
410         endCompression();
411         m_closed = true;
412         super.close();
413         m_bsStream.close();
414     }
415 
416     public void finalize() throws Throwable {
417         close();
418     }
419 
420     public void flush() throws IOException {
421         super.flush();
422         m_bsStream.flush();
423     }
424 
425     /***
426      * modified by Oliver Merkel, 010128
427      * 
428      * @param bv
429      *            Description of Parameter
430      * @exception java.io.IOException
431      *                Description of Exception
432      */
433     public void write(int bv) throws IOException {
434         int b = (256 + bv) % 256;
435         if (m_currentChar != -1) {
436             if (m_currentChar == b) {
437                 m_runLength++;
438                 if (m_runLength > 254) {
439                     writeRun();
440                     m_currentChar = -1;
441                     m_runLength = 0;
442                 }
443             } else {
444                 writeRun();
445                 m_runLength = 1;
446                 m_currentChar = b;
447             }
448         } else {
449             m_currentChar = b;
450             m_runLength++;
451         }
452     }
453 
454     private void allocateCompressStructures() {
455         int n = BASE_BLOCK_SIZE * m_blockSize100k;
456         m_block = new char[(n + 1 + NUM_OVERSHOOT_BYTES)];
457         m_quadrant = new int[(n + NUM_OVERSHOOT_BYTES)];
458         m_zptr = new int[n];
459         m_ftab = new int[65537];
460 
461         if (m_block == null || m_quadrant == null || m_zptr == null
462                 || m_ftab == null) {
463             // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n +
464             // NUM_OVERSHOOT_BYTES) + n + 65537;
465             // compressOutOfMemory ( totalDraw, n );
466         }
467 
468         /*
469          * The back end needs a place to store the MTF values whilst it
470          * calculates the coding tables. We could put them in the zptr array.
471          * However, these values will fit in a short, so we overlay szptr at the
472          * start of zptr, in the hope of reducing the number of cache misses
473          * induced by the multiple traversals of the MTF values when calculating
474          * coding tables. Seems to improve compression speed by about 1%.
475          */
476         // szptr = zptr;
477         m_szptr = new short[2 * n];
478     }
479 
480     private void bsFinishedWithStream() throws IOException {
481         while (m_bsLive > 0) {
482             int ch = (m_bsBuff >> 24);
483             try {
484                 m_bsStream.write(ch);// write 8-bit
485             } catch (IOException e) {
486                 throw e;
487             }
488             m_bsBuff <<= 8;
489             m_bsLive -= 8;
490         }
491     }
492 
493     private void bsPutIntVS(int numBits, int c) throws IOException {
494         bsW(numBits, c);
495     }
496 
497     private void bsPutUChar(int c) throws IOException {
498         bsW(8, c);
499     }
500 
501     private void bsPutint(int u) throws IOException {
502         bsW(8, (u >> 24) & 0xff);
503         bsW(8, (u >> 16) & 0xff);
504         bsW(8, (u >> 8) & 0xff);
505         bsW(8, u & 0xff);
506     }
507 
508     private void bsSetStream(OutputStream f) {
509         m_bsStream = f;
510         m_bsLive = 0;
511         m_bsBuff = 0;
512     }
513 
514     private void bsW(int n, int v) throws IOException {
515         while (m_bsLive >= 8) {
516             int ch = (m_bsBuff >> 24);
517             try {
518                 m_bsStream.write(ch);// write 8-bit
519             } catch (IOException e) {
520                 throw e;
521             }
522             m_bsBuff <<= 8;
523             m_bsLive -= 8;
524         }
525         m_bsBuff |= (v << (32 - m_bsLive - n));
526         m_bsLive += n;
527     }
528 
529     private void doReversibleTransformation() {
530         int i;
531 
532         m_workLimit = m_workFactor * m_last;
533         m_workDone = 0;
534         m_blockRandomised = false;
535         m_firstAttempt = true;
536 
537         mainSort();
538 
539         if (m_workDone > m_workLimit && m_firstAttempt) {
540             randomiseBlock();
541             m_workLimit = 0;
542             m_workDone = 0;
543             m_blockRandomised = true;
544             m_firstAttempt = false;
545             mainSort();
546         }
547 
548         m_origPtr = -1;
549         for (i = 0; i <= m_last; i++) {
550             if (m_zptr[i] == 0) {
551                 m_origPtr = i;
552                 break;
553             }
554         }
555         ;
556 
557         if (m_origPtr == -1) {
558             panic();
559         }
560     }
561 
562     private void endBlock() throws IOException {
563         m_blockCRC = m_crc.getFinalCRC();
564         m_combinedCRC = (m_combinedCRC << 1) | (m_combinedCRC >>> 31);
565         m_combinedCRC ^= m_blockCRC;
566 
567         /*
568          * sort the block and establish posn of original string
569          */
570         doReversibleTransformation();
571 
572         /*
573          * A 6-byte block header, the value chosen arbitrarily as 0x314159265359
574          * :-). A 32 bit value does not really give a strong enough guarantee
575          * that the value will not appear by chance in the compressed
576          * datastream. Worst-case probability of this event, for a 900k block,
577          * is about 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48
578          * bits. For a compressed file of size 100Gb -- about 100000 blocks --
579          * only a 48-bit marker will do. NB: normal compression/ decompression
580          * do *not* rely on these statistical properties. They are only
581          * important when trying to recover blocks from damaged files.
582          */
583         bsPutUChar(0x31);
584         bsPutUChar(0x41);
585         bsPutUChar(0x59);
586         bsPutUChar(0x26);
587         bsPutUChar(0x53);
588         bsPutUChar(0x59);
589 
590         /*
591          * Now the block's CRC, so it is in a known place.
592          */
593         bsPutint(m_blockCRC);
594 
595         /*
596          * Now a single bit indicating randomisation.
597          */
598         if (m_blockRandomised) {
599             bsW(1, 1);
600         } else {
601             bsW(1, 0);
602         }
603 
604         /*
605          * Finally, block's contents proper.
606          */
607         moveToFrontCodeAndSend();
608     }
609 
610     private void endCompression() throws IOException {
611         /*
612          * Now another magic 48-bit number, 0x177245385090, to indicate the end
613          * of the last block. (sqrt(pi), if you want to know. I did want to use
614          * e, but it contains too much repetition -- 27 18 28 18 28 46 -- for me
615          * to feel statistically comfortable. Call me paranoid.)
616          */
617         bsPutUChar(0x17);
618         bsPutUChar(0x72);
619         bsPutUChar(0x45);
620         bsPutUChar(0x38);
621         bsPutUChar(0x50);
622         bsPutUChar(0x90);
623 
624         bsPutint(m_combinedCRC);
625 
626         bsFinishedWithStream();
627     }
628 
629     private boolean fullGtU(int i1, int i2) {
630         int k;
631         char c1;
632         char c2;
633         int s1;
634         int s2;
635 
636         c1 = m_block[i1 + 1];
637         c2 = m_block[i2 + 1];
638         if (c1 != c2) {
639             return (c1 > c2);
640         }
641         i1++;
642         i2++;
643 
644         c1 = m_block[i1 + 1];
645         c2 = m_block[i2 + 1];
646         if (c1 != c2) {
647             return (c1 > c2);
648         }
649         i1++;
650         i2++;
651 
652         c1 = m_block[i1 + 1];
653         c2 = m_block[i2 + 1];
654         if (c1 != c2) {
655             return (c1 > c2);
656         }
657         i1++;
658         i2++;
659 
660         c1 = m_block[i1 + 1];
661         c2 = m_block[i2 + 1];
662         if (c1 != c2) {
663             return (c1 > c2);
664         }
665         i1++;
666         i2++;
667 
668         c1 = m_block[i1 + 1];
669         c2 = m_block[i2 + 1];
670         if (c1 != c2) {
671             return (c1 > c2);
672         }
673         i1++;
674         i2++;
675 
676         c1 = m_block[i1 + 1];
677         c2 = m_block[i2 + 1];
678         if (c1 != c2) {
679             return (c1 > c2);
680         }
681         i1++;
682         i2++;
683 
684         k = m_last + 1;
685 
686         do {
687             c1 = m_block[i1 + 1];
688             c2 = m_block[i2 + 1];
689             if (c1 != c2) {
690                 return (c1 > c2);
691             }
692             s1 = m_quadrant[i1];
693             s2 = m_quadrant[i2];
694             if (s1 != s2) {
695                 return (s1 > s2);
696             }
697             i1++;
698             i2++;
699 
700             c1 = m_block[i1 + 1];
701             c2 = m_block[i2 + 1];
702             if (c1 != c2) {
703                 return (c1 > c2);
704             }
705             s1 = m_quadrant[i1];
706             s2 = m_quadrant[i2];
707             if (s1 != s2) {
708                 return (s1 > s2);
709             }
710             i1++;
711             i2++;
712 
713             c1 = m_block[i1 + 1];
714             c2 = m_block[i2 + 1];
715             if (c1 != c2) {
716                 return (c1 > c2);
717             }
718             s1 = m_quadrant[i1];
719             s2 = m_quadrant[i2];
720             if (s1 != s2) {
721                 return (s1 > s2);
722             }
723             i1++;
724             i2++;
725 
726             c1 = m_block[i1 + 1];
727             c2 = m_block[i2 + 1];
728             if (c1 != c2) {
729                 return (c1 > c2);
730             }
731             s1 = m_quadrant[i1];
732             s2 = m_quadrant[i2];
733             if (s1 != s2) {
734                 return (s1 > s2);
735             }
736             i1++;
737             i2++;
738 
739             if (i1 > m_last) {
740                 i1 -= m_last;
741                 i1--;
742             }
743             ;
744             if (i2 > m_last) {
745                 i2 -= m_last;
746                 i2--;
747             }
748             ;
749 
750             k -= 4;
751             m_workDone++;
752         } while (k >= 0);
753 
754         return false;
755     }
756 
757     private void generateMTFValues() {
758         char[] yy = new char[256];
759         int i;
760         int j;
761         char tmp;
762         char tmp2;
763         int zPend;
764         int wr;
765         int EOB;
766 
767         makeMaps();
768         EOB = m_nInUse + 1;
769 
770         for (i = 0; i <= EOB; i++) {
771             m_mtfFreq[i] = 0;
772         }
773 
774         wr = 0;
775         zPend = 0;
776         for (i = 0; i < m_nInUse; i++) {
777             yy[i] = (char) i;
778         }
779 
780         for (i = 0; i <= m_last; i++) {
781             char ll_i;
782 
783             ll_i = m_unseqToSeq[m_block[m_zptr[i]]];
784 
785             j = 0;
786             tmp = yy[j];
787             while (ll_i != tmp) {
788                 j++;
789                 tmp2 = tmp;
790                 tmp = yy[j];
791                 yy[j] = tmp2;
792             }
793             ;
794             yy[0] = tmp;
795 
796             if (j == 0) {
797                 zPend++;
798             } else {
799                 if (zPend > 0) {
800                     zPend--;
801                     while (true) {
802                         switch (zPend % 2) {
803                         case 0:
804                             m_szptr[wr] = (short) RUNA;
805                             wr++;
806                             m_mtfFreq[RUNA]++;
807                             break;
808                         case 1:
809                             m_szptr[wr] = (short) RUNB;
810                             wr++;
811                             m_mtfFreq[RUNB]++;
812                             break;
813                         }
814                         ;
815                         if (zPend < 2) {
816                             break;
817                         }
818                         zPend = (zPend - 2) / 2;
819                     }
820                     ;
821                     zPend = 0;
822                 }
823                 m_szptr[wr] = (short) (j + 1);
824                 wr++;
825                 m_mtfFreq[j + 1]++;
826             }
827         }
828 
829         if (zPend > 0) {
830             zPend--;
831             while (true) {
832                 switch (zPend % 2) {
833                 case 0:
834                     m_szptr[wr] = (short) RUNA;
835                     wr++;
836                     m_mtfFreq[RUNA]++;
837                     break;
838                 case 1:
839                     m_szptr[wr] = (short) RUNB;
840                     wr++;
841                     m_mtfFreq[RUNB]++;
842                     break;
843                 }
844                 if (zPend < 2) {
845                     break;
846                 }
847                 zPend = (zPend - 2) / 2;
848             }
849         }
850 
851         m_szptr[wr] = (short) EOB;
852         wr++;
853         m_mtfFreq[EOB]++;
854 
855         m_nMTF = wr;
856     }
857 
858     private void hbAssignCodes(int[] code, char[] length, int minLen,
859             int maxLen, int alphaSize) {
860         int n;
861         int vec;
862         int i;
863 
864         vec = 0;
865         for (n = minLen; n <= maxLen; n++) {
866             for (i = 0; i < alphaSize; i++) {
867                 if (length[i] == n) {
868                     code[i] = vec;
869                     vec++;
870                 }
871             }
872             ;
873             vec <<= 1;
874         }
875     }
876 
877     private void initBlock() {
878         // blockNo++;
879         m_crc.initialiseCRC();
880         m_last = -1;
881         // ch = 0;
882 
883         for (int i = 0; i < 256; i++) {
884             m_inUse[i] = false;
885         }
886 
887         /*
888          * 20 is just a paranoia constant
889          */
890         m_allowableBlockSize = BASE_BLOCK_SIZE * m_blockSize100k - 20;
891     }
892 
893     private void initialize() throws IOException {
894         /*
895          * Write `magic' bytes h indicating file-format == huffmanised, followed
896          * by a digit indicating blockSize100k.
897          */
898         bsPutUChar('h');
899         bsPutUChar('0' + m_blockSize100k);
900 
901         m_combinedCRC = 0;
902     }
903 
904     private void mainSort() {
905         int i;
906         int j;
907         int ss;
908         int sb;
909         int[] runningOrder = new int[256];
910         int[] copy = new int[256];
911         boolean[] bigDone = new boolean[256];
912         int c1;
913         int c2;
914 
915         /*
916          * In the various block-sized structures, live data runs from 0 to
917          * last+NUM_OVERSHOOT_BYTES inclusive. First, set up the overshoot area
918          * for block.
919          */
920         // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" );
921         for (i = 0; i < NUM_OVERSHOOT_BYTES; i++) {
922             m_block[m_last + i + 2] = m_block[(i % (m_last + 1)) + 1];
923         }
924         for (i = 0; i <= m_last + NUM_OVERSHOOT_BYTES; i++) {
925             m_quadrant[i] = 0;
926         }
927 
928         m_block[0] = m_block[m_last + 1];
929 
930         if (m_last < 4000) {
931             /*
932              * Use simpleSort(), since the full sorting mechanism has quite a
933              * large constant overhead.
934              */
935             for (i = 0; i <= m_last; i++) {
936                 m_zptr[i] = i;
937             }
938             m_firstAttempt = false;
939             m_workDone = 0;
940             m_workLimit = 0;
941             simpleSort(0, m_last, 0);
942         } else {
943             for (i = 0; i <= 255; i++) {
944                 bigDone[i] = false;
945             }
946 
947             for (i = 0; i <= 65536; i++) {
948                 m_ftab[i] = 0;
949             }
950 
951             c1 = m_block[0];
952             for (i = 0; i <= m_last; i++) {
953                 c2 = m_block[i + 1];
954                 m_ftab[(c1 << 8) + c2]++;
955                 c1 = c2;
956             }
957 
958             for (i = 1; i <= 65536; i++) {
959                 m_ftab[i] += m_ftab[i - 1];
960             }
961 
962             c1 = m_block[1];
963             for (i = 0; i < m_last; i++) {
964                 c2 = m_block[i + 2];
965                 j = (c1 << 8) + c2;
966                 c1 = c2;
967                 m_ftab[j]--;
968                 m_zptr[m_ftab[j]] = i;
969             }
970 
971             j = ((m_block[m_last + 1]) << 8) + (m_block[1]);
972             m_ftab[j]--;
973             m_zptr[m_ftab[j]] = m_last;
974 
975             /*
976              * Now ftab contains the first loc of every small bucket. Calculate
977              * the running order, from smallest to largest big bucket.
978              */
979             for (i = 0; i <= 255; i++) {
980                 runningOrder[i] = i;
981             }
982             {
983                 int vv;
984                 int h = 1;
985                 do {
986                     h = 3 * h + 1;
987                 } while (h <= 256);
988                 do {
989                     h = h / 3;
990                     for (i = h; i <= 255; i++) {
991                         vv = runningOrder[i];
992                         j = i;
993                         while ((m_ftab[((runningOrder[j - h]) + 1) << 8] - m_ftab[(runningOrder[j
994                                 - h]) << 8]) > (m_ftab[((vv) + 1) << 8] - m_ftab[(vv) << 8])) {
995                             runningOrder[j] = runningOrder[j - h];
996                             j = j - h;
997                             if (j <= (h - 1)) {
998                                 break;
999                             }
1000                         }
1001                         runningOrder[j] = vv;
1002                     }
1003                 } while (h != 1);
1004             }
1005 
1006             /*
1007              * The main sorting loop.
1008              */
1009             for (i = 0; i <= 255; i++) {
1010 
1011                 /*
1012                  * Process big buckets, starting with the least full.
1013                  */
1014                 ss = runningOrder[i];
1015 
1016                 /*
1017                  * Complete the big bucket [ss] by quicksorting any unsorted
1018                  * small buckets [ss, j]. Hopefully previous pointer-scanning
1019                  * phases have already completed many of the small buckets [ss,
1020                  * j], so we don't have to sort them at all.
1021                  */
1022                 for (j = 0; j <= 255; j++) {
1023                     sb = (ss << 8) + j;
1024                     if (!((m_ftab[sb] & SETMASK) == SETMASK)) {
1025                         int lo = m_ftab[sb] & CLEARMASK;
1026                         int hi = (m_ftab[sb + 1] & CLEARMASK) - 1;
1027                         if (hi > lo) {
1028                             qSort3(lo, hi, 2);
1029                             if (m_workDone > m_workLimit && m_firstAttempt) {
1030                                 return;
1031                             }
1032                         }
1033                         m_ftab[sb] |= SETMASK;
1034                     }
1035                 }
1036 
1037                 /*
1038                  * The ss big bucket is now done. Record this fact, and update
1039                  * the quadrant descriptors. Remember to update quadrants in the
1040                  * overshoot area too, if necessary. The "if (i < 255)" test
1041                  * merely skips this updating for the last bucket processed,
1042                  * since updating for the last bucket is pointless.
1043                  */
1044                 bigDone[ss] = true;
1045 
1046                 if (i < 255) {
1047                     int bbStart = m_ftab[ss << 8] & CLEARMASK;
1048                     int bbSize = (m_ftab[(ss + 1) << 8] & CLEARMASK) - bbStart;
1049                     int shifts = 0;
1050 
1051                     while ((bbSize >> shifts) > 65534) {
1052                         shifts++;
1053                     }
1054 
1055                     for (j = 0; j < bbSize; j++) {
1056                         int a2update = m_zptr[bbStart + j];
1057                         int qVal = (j >> shifts);
1058                         m_quadrant[a2update] = qVal;
1059                         if (a2update < NUM_OVERSHOOT_BYTES) {
1060                             m_quadrant[a2update + m_last + 1] = qVal;
1061                         }
1062                     }
1063 
1064                     if (!(((bbSize - 1) >> shifts) <= 65535)) {
1065                         panic();
1066                     }
1067                 }
1068 
1069                 /*
1070                  * Now scan this big bucket so as to synthesise the sorted order
1071                  * for small buckets [t, ss] for all t != ss.
1072                  */
1073                 for (j = 0; j <= 255; j++) {
1074                     copy[j] = m_ftab[(j << 8) + ss] & CLEARMASK;
1075                 }
1076 
1077                 for (j = m_ftab[ss << 8] & CLEARMASK; j < (m_ftab[(ss + 1) << 8] & CLEARMASK); j++) {
1078                     c1 = m_block[m_zptr[j]];
1079                     if (!bigDone[c1]) {
1080                         m_zptr[copy[c1]] = m_zptr[j] == 0 ? m_last
1081                                 : m_zptr[j] - 1;
1082                         copy[c1]++;
1083                     }
1084                 }
1085 
1086                 for (j = 0; j <= 255; j++) {
1087                     m_ftab[(j << 8) + ss] |= SETMASK;
1088                 }
1089             }
1090         }
1091     }
1092 
1093     private void makeMaps() {
1094         int i;
1095         m_nInUse = 0;
1096         for (i = 0; i < 256; i++) {
1097             if (m_inUse[i]) {
1098                 m_seqToUnseq[m_nInUse] = (char) i;
1099                 m_unseqToSeq[i] = (char) m_nInUse;
1100                 m_nInUse++;
1101             }
1102         }
1103     }
1104 
1105     private char med3(char a, char b, char c) {
1106         char t;
1107         if (a > b) {
1108             t = a;
1109             a = b;
1110             b = t;
1111         }
1112         if (b > c) {
1113             t = b;
1114             b = c;
1115             c = t;
1116         }
1117         if (a > b) {
1118             b = a;
1119         }
1120         return b;
1121     }
1122 
1123     private void moveToFrontCodeAndSend() throws IOException {
1124         bsPutIntVS(24, m_origPtr);
1125         generateMTFValues();
1126         sendMTFValues();
1127     }
1128 
1129     private void qSort3(int loSt, int hiSt, int dSt) {
1130         int unLo;
1131         int unHi;
1132         int ltLo;
1133         int gtHi;
1134         int med;
1135         int n;
1136         int m;
1137         int sp;
1138         int lo;
1139         int hi;
1140         int d;
1141         StackElem[] stack = new StackElem[QSORT_STACK_SIZE];
1142         for (int count = 0; count < QSORT_STACK_SIZE; count++) {
1143             stack[count] = new StackElem();
1144         }
1145 
1146         sp = 0;
1147 
1148         stack[sp].m_ll = loSt;
1149         stack[sp].m_hh = hiSt;
1150         stack[sp].m_dd = dSt;
1151         sp++;
1152 
1153         while (sp > 0) {
1154             if (sp >= QSORT_STACK_SIZE) {
1155                 panic();
1156             }
1157 
1158             sp--;
1159             lo = stack[sp].m_ll;
1160             hi = stack[sp].m_hh;
1161             d = stack[sp].m_dd;
1162 
1163             if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
1164                 simpleSort(lo, hi, d);
1165                 if (m_workDone > m_workLimit && m_firstAttempt) {
1166                     return;
1167                 }
1168                 continue;
1169             }
1170 
1171             med = med3(m_block[m_zptr[lo] + d + 1],
1172                     m_block[m_zptr[hi] + d + 1], m_block[m_zptr[(lo + hi) >> 1]
1173                             + d + 1]);
1174 
1175             unLo = lo;
1176             ltLo = lo;
1177             unHi = hi;
1178             gtHi = hi;
1179 
1180             while (true) {
1181                 while (true) {
1182                     if (unLo > unHi) {
1183                         break;
1184                     }
1185                     n = m_block[m_zptr[unLo] + d + 1] - med;
1186                     if (n == 0) {
1187                         int temp = 0;
1188                         temp = m_zptr[unLo];
1189                         m_zptr[unLo] = m_zptr[ltLo];
1190                         m_zptr[ltLo] = temp;
1191                         ltLo++;
1192                         unLo++;
1193                         continue;
1194                     }
1195                     ;
1196                     if (n > 0) {
1197                         break;
1198                     }
1199                     unLo++;
1200                 }
1201                 while (true) {
1202                     if (unLo > unHi) {
1203                         break;
1204                     }
1205                     n = m_block[m_zptr[unHi] + d + 1] - med;
1206                     if (n == 0) {
1207                         int temp = 0;
1208                         temp = m_zptr[unHi];
1209                         m_zptr[unHi] = m_zptr[gtHi];
1210                         m_zptr[gtHi] = temp;
1211                         gtHi--;
1212                         unHi--;
1213                         continue;
1214                     }
1215                     ;
1216                     if (n < 0) {
1217                         break;
1218                     }
1219                     unHi--;
1220                 }
1221                 if (unLo > unHi) {
1222                     break;
1223                 }
1224                 int temp = 0;
1225                 temp = m_zptr[unLo];
1226                 m_zptr[unLo] = m_zptr[unHi];
1227                 m_zptr[unHi] = temp;
1228                 unLo++;
1229                 unHi--;
1230             }
1231 
1232             if (gtHi < ltLo) {
1233                 stack[sp].m_ll = lo;
1234                 stack[sp].m_hh = hi;
1235                 stack[sp].m_dd = d + 1;
1236                 sp++;
1237                 continue;
1238             }
1239 
1240             n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo) : (unLo - ltLo);
1241             vswap(lo, unLo - n, n);
1242             m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi) : (gtHi - unHi);
1243             vswap(unLo, hi - m + 1, m);
1244 
1245             n = lo + unLo - ltLo - 1;
1246             m = hi - (gtHi - unHi) + 1;
1247 
1248             stack[sp].m_ll = lo;
1249             stack[sp].m_hh = n;
1250             stack[sp].m_dd = d;
1251             sp++;
1252 
1253             stack[sp].m_ll = n + 1;
1254             stack[sp].m_hh = m - 1;
1255             stack[sp].m_dd = d + 1;
1256             sp++;
1257 
1258             stack[sp].m_ll = m;
1259             stack[sp].m_hh = hi;
1260             stack[sp].m_dd = d;
1261             sp++;
1262         }
1263     }
1264 
1265     private void randomiseBlock() {
1266         int i;
1267         int rNToGo = 0;
1268         int rTPos = 0;
1269         for (i = 0; i < 256; i++) {
1270             m_inUse[i] = false;
1271         }
1272 
1273         for (i = 0; i <= m_last; i++) {
1274             if (rNToGo == 0) {
1275                 rNToGo = (char) RAND_NUMS[rTPos];
1276                 rTPos++;
1277                 if (rTPos == 512) {
1278                     rTPos = 0;
1279                 }
1280             }
1281             rNToGo--;
1282             m_block[i + 1] ^= ((rNToGo == 1) ? 1 : 0);
1283             // handle 16 bit signed numbers
1284             m_block[i + 1] &= 0xFF;
1285 
1286             m_inUse[m_block[i + 1]] = true;
1287         }
1288     }
1289 
1290     private void sendMTFValues() throws IOException {
1291         char[][] len = new char[N_GROUPS][MAX_ALPHA_SIZE];
1292 
1293         int v;
1294 
1295         int t;
1296 
1297         int i;
1298 
1299         int j;
1300 
1301         int gs;
1302 
1303         int ge;
1304 
1305         int bt;
1306 
1307         int bc;
1308 
1309         int iter;
1310         int nSelectors = 0;
1311         int alphaSize;
1312         int minLen;
1313         int maxLen;
1314         int selCtr;
1315         int nGroups;
1316 
1317         alphaSize = m_nInUse + 2;
1318         for (t = 0; t < N_GROUPS; t++) {
1319             for (v = 0; v < alphaSize; v++) {
1320                 len[t][v] = (char) GREATER_ICOST;
1321             }
1322         }
1323 
1324         /*
1325          * Decide how many coding tables to use
1326          */
1327         if (m_nMTF <= 0) {
1328             panic();
1329         }
1330 
1331         if (m_nMTF < 200) {
1332             nGroups = 2;
1333         } else if (m_nMTF < 600) {
1334             nGroups = 3;
1335         } else if (m_nMTF < 1200) {
1336             nGroups = 4;
1337         } else if (m_nMTF < 2400) {
1338             nGroups = 5;
1339         } else {
1340             nGroups = 6;
1341         }
1342         {
1343             /*
1344              * Generate an initial set of coding tables
1345              */
1346             int nPart;
1347             int remF;
1348             int tFreq;
1349             int aFreq;
1350 
1351             nPart = nGroups;
1352             remF = m_nMTF;
1353             gs = 0;
1354             while (nPart > 0) {
1355                 tFreq = remF / nPart;
1356                 ge = gs - 1;
1357                 aFreq = 0;
1358                 while (aFreq < tFreq && ge < alphaSize - 1) {
1359                     ge++;
1360                     aFreq += m_mtfFreq[ge];
1361                 }
1362 
1363                 if (ge > gs && nPart != nGroups && nPart != 1
1364                         && ((nGroups - nPart) % 2 == 1)) {
1365                     aFreq -= m_mtfFreq[ge];
1366                     ge--;
1367                 }
1368 
1369                 for (v = 0; v < alphaSize; v++) {
1370                     if (v >= gs && v <= ge) {
1371                         len[nPart - 1][v] = (char) LESSER_ICOST;
1372                     } else {
1373                         len[nPart - 1][v] = (char) GREATER_ICOST;
1374                     }
1375                 }
1376 
1377                 nPart--;
1378                 gs = ge + 1;
1379                 remF -= aFreq;
1380             }
1381         }
1382 
1383         int[][] rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE];
1384         int[] fave = new int[N_GROUPS];
1385         short[] cost = new short[N_GROUPS];
1386         /*
1387          * Iterate up to N_ITERS times to improve the tables.
1388          */
1389         for (iter = 0; iter < N_ITERS; iter++) {
1390             for (t = 0; t < nGroups; t++) {
1391                 fave[t] = 0;
1392             }
1393 
1394             for (t = 0; t < nGroups; t++) {
1395                 for (v = 0; v < alphaSize; v++) {
1396                     rfreq[t][v] = 0;
1397                 }
1398             }
1399 
1400             nSelectors = 0;
1401             gs = 0;
1402             while (true) {
1403 
1404                 /*
1405                  * Set group start & end marks.
1406                  */
1407                 if (gs >= m_nMTF) {
1408                     break;
1409                 }
1410                 ge = gs + G_SIZE - 1;
1411                 if (ge >= m_nMTF) {
1412                     ge = m_nMTF - 1;
1413                 }
1414 
1415                 /*
1416                  * Calculate the cost of this group as coded by each of the
1417                  * coding tables.
1418                  */
1419                 for (t = 0; t < nGroups; t++) {
1420                     cost[t] = 0;
1421                 }
1422 
1423                 if (nGroups == 6) {
1424                     short cost0 = 0;
1425                     short cost1 = 0;
1426                     short cost2 = 0;
1427                     short cost3 = 0;
1428                     short cost4 = 0;
1429                     short cost5 = 0;
1430 
1431                     for (i = gs; i <= ge; i++) {
1432                         short icv = m_szptr[i];
1433                         cost0 += len[0][icv];
1434                         cost1 += len[1][icv];
1435                         cost2 += len[2][icv];
1436                         cost3 += len[3][icv];
1437                         cost4 += len[4][icv];
1438                         cost5 += len[5][icv];
1439                     }
1440                     cost[0] = cost0;
1441                     cost[1] = cost1;
1442                     cost[2] = cost2;
1443                     cost[3] = cost3;
1444                     cost[4] = cost4;
1445                     cost[5] = cost5;
1446                 } else {
1447                     for (i = gs; i <= ge; i++) {
1448                         short icv = m_szptr[i];
1449                         for (t = 0; t < nGroups; t++) {
1450                             cost[t] += len[t][icv];
1451                         }
1452                     }
1453                 }
1454 
1455                 /*
1456                  * Find the coding table which is best for this group, and
1457                  * record its identity in the selector table.
1458                  */
1459                 bc = 999999999;
1460                 bt = -1;
1461                 for (t = 0; t < nGroups; t++) {
1462                     if (cost[t] < bc) {
1463                         bc = cost[t];
1464                         bt = t;
1465                     }
1466                 }
1467                 ;
1468                 fave[bt]++;
1469                 m_selector[nSelectors] = (char) bt;
1470                 nSelectors++;
1471 
1472                 /*
1473                  * Increment the symbol frequencies for the selected table.
1474                  */
1475                 for (i = gs; i <= ge; i++) {
1476                     rfreq[bt][m_szptr[i]]++;
1477                 }
1478 
1479                 gs = ge + 1;
1480             }
1481 
1482             /*
1483              * Recompute the tables based on the accumulated frequencies.
1484              */
1485             for (t = 0; t < nGroups; t++) {
1486                 hbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
1487             }
1488         }
1489 
1490         rfreq = null;
1491         fave = null;
1492         cost = null;
1493 
1494         if (!(nGroups < 8)) {
1495             panic();
1496         }
1497         if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / G_SIZE)))) {
1498             panic();
1499         }
1500         {
1501             /*
1502              * Compute MTF values for the selectors.
1503              */
1504             char[] pos = new char[N_GROUPS];
1505             char ll_i;
1506             char tmp2;
1507             char tmp;
1508             for (i = 0; i < nGroups; i++) {
1509                 pos[i] = (char) i;
1510             }
1511             for (i = 0; i < nSelectors; i++) {
1512                 ll_i = m_selector[i];
1513                 j = 0;
1514                 tmp = pos[j];
1515                 while (ll_i != tmp) {
1516                     j++;
1517                     tmp2 = tmp;
1518                     tmp = pos[j];
1519                     pos[j] = tmp2;
1520                 }
1521                 pos[0] = tmp;
1522                 m_selectorMtf[i] = (char) j;
1523             }
1524         }
1525 
1526         int[][] code = new int[N_GROUPS][MAX_ALPHA_SIZE];
1527 
1528         /*
1529          * Assign actual codes for the tables.
1530          */
1531         for (t = 0; t < nGroups; t++) {
1532             minLen = 32;
1533             maxLen = 0;
1534             for (i = 0; i < alphaSize; i++) {
1535                 if (len[t][i] > maxLen) {
1536                     maxLen = len[t][i];
1537                 }
1538                 if (len[t][i] < minLen) {
1539                     minLen = len[t][i];
1540                 }
1541             }
1542             if (maxLen > 20) {
1543                 panic();
1544             }
1545             if (minLen < 1) {
1546                 panic();
1547             }
1548             hbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
1549         }
1550         {
1551             /*
1552              * Transmit the mapping table.
1553              */
1554             boolean[] inUse16 = new boolean[16];
1555             for (i = 0; i < 16; i++) {
1556                 inUse16[i] = false;
1557                 for (j = 0; j < 16; j++) {
1558                     if (m_inUse[i * 16 + j]) {
1559                         inUse16[i] = true;
1560                     }
1561                 }
1562             }
1563 
1564             for (i = 0; i < 16; i++) {
1565                 if (inUse16[i]) {
1566                     bsW(1, 1);
1567                 } else {
1568                     bsW(1, 0);
1569                 }
1570             }
1571 
1572             for (i = 0; i < 16; i++) {
1573                 if (inUse16[i]) {
1574                     for (j = 0; j < 16; j++) {
1575                         if (m_inUse[i * 16 + j]) {
1576                             bsW(1, 1);
1577                         } else {
1578                             bsW(1, 0);
1579                         }
1580                     }
1581                 }
1582             }
1583 
1584         }
1585 
1586         /*
1587          * Now the selectors.
1588          */
1589         bsW(3, nGroups);
1590         bsW(15, nSelectors);
1591         for (i = 0; i < nSelectors; i++) {
1592             for (j = 0; j < m_selectorMtf[i]; j++) {
1593                 bsW(1, 1);
1594             }
1595             bsW(1, 0);
1596         }
1597 
1598         for (t = 0; t < nGroups; t++) {
1599             int curr = len[t][0];
1600             bsW(5, curr);
1601             for (i = 0; i < alphaSize; i++) {
1602                 while (curr < len[t][i]) {
1603                     bsW(2, 2);
1604                     curr++;
1605                     /*
1606                      * 10
1607                      */
1608                 }
1609                 while (curr > len[t][i]) {
1610                     bsW(2, 3);
1611                     curr--;
1612                     /*
1613                      * 11
1614                      */
1615                 }
1616                 bsW(1, 0);
1617             }
1618         }
1619 
1620         /*
1621          * And finally, the block data proper
1622          */
1623         selCtr = 0;
1624         gs = 0;
1625         while (true) {
1626             if (gs >= m_nMTF) {
1627                 break;
1628             }
1629             ge = gs + G_SIZE - 1;
1630             if (ge >= m_nMTF) {
1631                 ge = m_nMTF - 1;
1632             }
1633             for (i = gs; i <= ge; i++) {
1634                 bsW(len[m_selector[selCtr]][m_szptr[i]],
1635                         code[m_selector[selCtr]][m_szptr[i]]);
1636             }
1637 
1638             gs = ge + 1;
1639             selCtr++;
1640         }
1641         if (!(selCtr == nSelectors)) {
1642             panic();
1643         }
1644     }
1645 
1646     private void simpleSort(int lo, int hi, int d) {
1647         int i;
1648         int j;
1649         int h;
1650         int bigN;
1651         int hp;
1652         int v;
1653 
1654         bigN = hi - lo + 1;
1655         if (bigN < 2) {
1656             return;
1657         }
1658 
1659         hp = 0;
1660         while (m_incs[hp] < bigN) {
1661             hp++;
1662         }
1663         hp--;
1664 
1665         for (; hp >= 0; hp--) {
1666             h = m_incs[hp];
1667 
1668             i = lo + h;
1669             while (true) {
1670                 /*
1671                  * copy 1
1672                  */
1673                 if (i > hi) {
1674                     break;
1675                 }
1676                 v = m_zptr[i];
1677                 j = i;
1678                 while (fullGtU(m_zptr[j - h] + d, v + d)) {
1679                     m_zptr[j] = m_zptr[j - h];
1680                     j = j - h;
1681                     if (j <= (lo + h - 1)) {
1682                         break;
1683                     }
1684                 }
1685                 m_zptr[j] = v;
1686                 i++;
1687 
1688                 /*
1689                  * copy 2
1690                  */
1691                 if (i > hi) {
1692                     break;
1693                 }
1694                 v = m_zptr[i];
1695                 j = i;
1696                 while (fullGtU(m_zptr[j - h] + d, v + d)) {
1697                     m_zptr[j] = m_zptr[j - h];
1698                     j = j - h;
1699                     if (j <= (lo + h - 1)) {
1700                         break;
1701                     }
1702                 }
1703                 m_zptr[j] = v;
1704                 i++;
1705 
1706                 /*
1707                  * copy 3
1708                  */
1709                 if (i > hi) {
1710                     break;
1711                 }
1712                 v = m_zptr[i];
1713                 j = i;
1714                 while (fullGtU(m_zptr[j - h] + d, v + d)) {
1715                     m_zptr[j] = m_zptr[j - h];
1716                     j = j - h;
1717                     if (j <= (lo + h - 1)) {
1718                         break;
1719                     }
1720                 }
1721                 m_zptr[j] = v;
1722                 i++;
1723 
1724                 if (m_workDone > m_workLimit && m_firstAttempt) {
1725                     return;
1726                 }
1727             }
1728         }
1729     }
1730 
1731     private void vswap(int p1, int p2, int n) {
1732         int temp = 0;
1733         while (n > 0) {
1734             temp = m_zptr[p1];
1735             m_zptr[p1] = m_zptr[p2];
1736             m_zptr[p2] = temp;
1737             p1++;
1738             p2++;
1739             n--;
1740         }
1741     }
1742 
1743     private void writeRun() throws IOException {
1744         if (m_last < m_allowableBlockSize) {
1745             m_inUse[m_currentChar] = true;
1746             for (int i = 0; i < m_runLength; i++) {
1747                 m_crc.updateCRC((char) m_currentChar);
1748             }
1749             switch (m_runLength) {
1750             case 1:
1751                 m_last++;
1752                 m_block[m_last + 1] = (char) m_currentChar;
1753                 break;
1754             case 2:
1755                 m_last++;
1756                 m_block[m_last + 1] = (char) m_currentChar;
1757                 m_last++;
1758                 m_block[m_last + 1] = (char) m_currentChar;
1759                 break;
1760             case 3:
1761                 m_last++;
1762                 m_block[m_last + 1] = (char) m_currentChar;
1763                 m_last++;
1764                 m_block[m_last + 1] = (char) m_currentChar;
1765                 m_last++;
1766                 m_block[m_last + 1] = (char) m_currentChar;
1767                 break;
1768             default:
1769                 m_inUse[m_runLength - 4] = true;
1770                 m_last++;
1771                 m_block[m_last + 1] = (char) m_currentChar;
1772                 m_last++;
1773                 m_block[m_last + 1] = (char) m_currentChar;
1774                 m_last++;
1775                 m_block[m_last + 1] = (char) m_currentChar;
1776                 m_last++;
1777                 m_block[m_last + 1] = (char) m_currentChar;
1778                 m_last++;
1779                 m_block[m_last + 1] = (char) (m_runLength - 4);
1780                 break;
1781             }
1782         } else {
1783             endBlock();
1784             initBlock();
1785             writeRun();
1786         }
1787     }
1788 
1789     private static class StackElem {
1790         int m_dd;
1791 
1792         int m_hh;
1793 
1794         int m_ll;
1795     }
1796 }