CBZip2OutputStream.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:56k
源码类别:

网格计算

开发平台:

Java

  1. /*
  2.  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3.  *  contributor license agreements.  See the NOTICE file distributed with
  4.  *  this work for additional information regarding copyright ownership.
  5.  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6.  *  (the "License"); you may not use this file except in compliance with
  7.  *  the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  *
  17.  */
  18. /*
  19.  * This package is based on the work done by Keiron Liddle, Aftex Software
  20.  * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
  21.  * great code.
  22.  */
  23. package org.apache.hadoop.io.compress.bzip2;
  24. import java.io.OutputStream;
  25. import java.io.IOException;
  26. /**
  27.  * An output stream that compresses into the BZip2 format (without the file
  28.  * header chars) into another stream.
  29.  *
  30.  * <p>
  31.  * The compression requires large amounts of memory. Thus you should call the
  32.  * {@link #close() close()} method as soon as possible, to force
  33.  * <tt>CBZip2OutputStream</tt> to release the allocated memory.
  34.  * </p>
  35.  *
  36.  * <p>
  37.  * You can shrink the amount of allocated memory and maybe raise the compression
  38.  * speed by choosing a lower blocksize, which in turn may cause a lower
  39.  * compression ratio. You can avoid unnecessary memory allocation by avoiding
  40.  * using a blocksize which is bigger than the size of the input.
  41.  * </p>
  42.  *
  43.  * <p>
  44.  * You can compute the memory usage for compressing by the following formula:
  45.  * </p>
  46.  *
  47.  * <pre>
  48.  * &lt;code&gt;400k + (9 * blocksize)&lt;/code&gt;.
  49.  * </pre>
  50.  *
  51.  * <p>
  52.  * To get the memory required for decompression by {@link CBZip2InputStream
  53.  * CBZip2InputStream} use
  54.  * </p>
  55.  *
  56.  * <pre>
  57.  * &lt;code&gt;65k + (5 * blocksize)&lt;/code&gt;.
  58.  * </pre>
  59.  *
  60.  * <table width="100%" border="1">
  61.  * <colgroup> <col width="33%" /> <col width="33%" /> <col width="33%" />
  62.  * </colgroup>
  63.  * <tr>
  64.  * <th colspan="3">Memory usage by blocksize</th>
  65.  * </tr>
  66.  * <tr>
  67.  * <th align="right">Blocksize</th> <th align="right">Compression<br>
  68.  * memory usage</th> <th align="right">Decompression<br>
  69.  * memory usage</th>
  70.  * </tr>
  71.  * <tr>
  72.  * <td align="right">100k</td>
  73.  * <td align="right">1300k</td>
  74.  * <td align="right">565k</td>
  75.  * </tr>
  76.  * <tr>
  77.  * <td align="right">200k</td>
  78.  * <td align="right">2200k</td>
  79.  * <td align="right">1065k</td>
  80.  * </tr>
  81.  * <tr>
  82.  * <td align="right">300k</td>
  83.  * <td align="right">3100k</td>
  84.  * <td align="right">1565k</td>
  85.  * </tr>
  86.  * <tr>
  87.  * <td align="right">400k</td>
  88.  * <td align="right">4000k</td>
  89.  * <td align="right">2065k</td>
  90.  * </tr>
  91.  * <tr>
  92.  * <td align="right">500k</td>
  93.  * <td align="right">4900k</td>
  94.  * <td align="right">2565k</td>
  95.  * </tr>
  96.  * <tr>
  97.  * <td align="right">600k</td>
  98.  * <td align="right">5800k</td>
  99.  * <td align="right">3065k</td>
  100.  * </tr>
  101.  * <tr>
  102.  * <td align="right">700k</td>
  103.  * <td align="right">6700k</td>
  104.  * <td align="right">3565k</td>
  105.  * </tr>
  106.  * <tr>
  107.  * <td align="right">800k</td>
  108.  * <td align="right">7600k</td>
  109.  * <td align="right">4065k</td>
  110.  * </tr>
  111.  * <tr>
  112.  * <td align="right">900k</td>
  113.  * <td align="right">8500k</td>
  114.  * <td align="right">4565k</td>
  115.  * </tr>
  116.  * </table>
  117.  *
  118.  * <p>
  119.  * For decompression <tt>CBZip2InputStream</tt> allocates less memory if the
  120.  * bzipped input is smaller than one block.
  121.  * </p>
  122.  *
  123.  * <p>
  124.  * Instances of this class are not threadsafe.
  125.  * </p>
  126.  *
  127.  * <p>
  128.  * TODO: Update to BZip2 1.0.1
  129.  * </p>
  130.  *
  131.  */
  132. public class CBZip2OutputStream extends OutputStream implements BZip2Constants {
  133.   /**
  134.   * The minimum supported blocksize <tt> == 1</tt>.
  135.   */
  136.   public static final int MIN_BLOCKSIZE = 1;
  137.   /**
  138.   * The maximum supported blocksize <tt> == 9</tt>.
  139.   */
  140.   public static final int MAX_BLOCKSIZE = 9;
  141.   /**
  142.   * This constant is accessible by subclasses for historical purposes. If you
  143.   * don't know what it means then you don't need it.
  144.   */
  145.   protected static final int SETMASK = (1 << 21);
  146.   /**
  147.   * This constant is accessible by subclasses for historical purposes. If you
  148.   * don't know what it means then you don't need it.
  149.   */
  150.   protected static final int CLEARMASK = (~SETMASK);
  151.   /**
  152.   * This constant is accessible by subclasses for historical purposes. If you
  153.   * don't know what it means then you don't need it.
  154.   */
  155.   protected static final int GREATER_ICOST = 15;
  156.   /**
  157.   * This constant is accessible by subclasses for historical purposes. If you
  158.   * don't know what it means then you don't need it.
  159.   */
  160.   protected static final int LESSER_ICOST = 0;
  161.   /**
  162.   * This constant is accessible by subclasses for historical purposes. If you
  163.   * don't know what it means then you don't need it.
  164.   */
  165.   protected static final int SMALL_THRESH = 20;
  166.   /**
  167.   * This constant is accessible by subclasses for historical purposes. If you
  168.   * don't know what it means then you don't need it.
  169.   */
  170.   protected static final int DEPTH_THRESH = 10;
  171.   /**
  172.   * This constant is accessible by subclasses for historical purposes. If you
  173.   * don't know what it means then you don't need it.
  174.   */
  175.   protected static final int WORK_FACTOR = 30;
  176.   /**
  177.   * This constant is accessible by subclasses for historical purposes. If you
  178.   * don't know what it means then you don't need it.
  179.   * <p>
  180.   * If you are ever unlucky/improbable enough to get a stack overflow whilst
  181.   * sorting, increase the following constant and try again. In practice I
  182.   * have never seen the stack go above 27 elems, so the following limit seems
  183.   * very generous.
  184.   * </p>
  185.   */
  186.   protected static final int QSORT_STACK_SIZE = 1000;
  187.   /**
  188.   * Knuth's increments seem to work better than Incerpi-Sedgewick here.
  189.   * Possibly because the number of elems to sort is usually small, typically
  190.   * &lt;= 20.
  191.   */
  192.   private static final int[] INCS = { 1, 4, 13, 40, 121, 364, 1093, 3280,
  193.       9841, 29524, 88573, 265720, 797161, 2391484 };
  194.   /**
  195.   * This method is accessible by subclasses for historical purposes. If you
  196.   * don't know what it does then you don't need it.
  197.   */
  198.   protected static void hbMakeCodeLengths(char[] len, int[] freq,
  199.       int alphaSize, int maxLen) {
  200.     /*
  201.     * Nodes and heap entries run from 1. Entry 0 for both the heap and
  202.     * nodes is a sentinel.
  203.     */
  204.     final int[] heap = new int[MAX_ALPHA_SIZE * 2];
  205.     final int[] weight = new int[MAX_ALPHA_SIZE * 2];
  206.     final int[] parent = new int[MAX_ALPHA_SIZE * 2];
  207.     for (int i = alphaSize; --i >= 0;) {
  208.       weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
  209.     }
  210.     for (boolean tooLong = true; tooLong;) {
  211.       tooLong = false;
  212.       int nNodes = alphaSize;
  213.       int nHeap = 0;
  214.       heap[0] = 0;
  215.       weight[0] = 0;
  216.       parent[0] = -2;
  217.       for (int i = 1; i <= alphaSize; i++) {
  218.         parent[i] = -1;
  219.         nHeap++;
  220.         heap[nHeap] = i;
  221.         int zz = nHeap;
  222.         int tmp = heap[zz];
  223.         while (weight[tmp] < weight[heap[zz >> 1]]) {
  224.           heap[zz] = heap[zz >> 1];
  225.           zz >>= 1;
  226.         }
  227.         heap[zz] = tmp;
  228.       }
  229.       // assert (nHeap < (MAX_ALPHA_SIZE + 2)) : nHeap;
  230.       while (nHeap > 1) {
  231.         int n1 = heap[1];
  232.         heap[1] = heap[nHeap];
  233.         nHeap--;
  234.         int yy = 0;
  235.         int zz = 1;
  236.         int tmp = heap[1];
  237.         while (true) {
  238.           yy = zz << 1;
  239.           if (yy > nHeap) {
  240.             break;
  241.           }
  242.           if ((yy < nHeap)
  243.               && (weight[heap[yy + 1]] < weight[heap[yy]])) {
  244.             yy++;
  245.           }
  246.           if (weight[tmp] < weight[heap[yy]]) {
  247.             break;
  248.           }
  249.           heap[zz] = heap[yy];
  250.           zz = yy;
  251.         }
  252.         heap[zz] = tmp;
  253.         int n2 = heap[1];
  254.         heap[1] = heap[nHeap];
  255.         nHeap--;
  256.         yy = 0;
  257.         zz = 1;
  258.         tmp = heap[1];
  259.         while (true) {
  260.           yy = zz << 1;
  261.           if (yy > nHeap) {
  262.             break;
  263.           }
  264.           if ((yy < nHeap)
  265.               && (weight[heap[yy + 1]] < weight[heap[yy]])) {
  266.             yy++;
  267.           }
  268.           if (weight[tmp] < weight[heap[yy]]) {
  269.             break;
  270.           }
  271.           heap[zz] = heap[yy];
  272.           zz = yy;
  273.         }
  274.         heap[zz] = tmp;
  275.         nNodes++;
  276.         parent[n1] = parent[n2] = nNodes;
  277.         final int weight_n1 = weight[n1];
  278.         final int weight_n2 = weight[n2];
  279.         weight[nNodes] = (((weight_n1 & 0xffffff00) + (weight_n2 & 0xffffff00)) | (1 + (((weight_n1 & 0x000000ff) > (weight_n2 & 0x000000ff)) ? (weight_n1 & 0x000000ff)
  280.             : (weight_n2 & 0x000000ff))));
  281.         parent[nNodes] = -1;
  282.         nHeap++;
  283.         heap[nHeap] = nNodes;
  284.         tmp = 0;
  285.         zz = nHeap;
  286.         tmp = heap[zz];
  287.         final int weight_tmp = weight[tmp];
  288.         while (weight_tmp < weight[heap[zz >> 1]]) {
  289.           heap[zz] = heap[zz >> 1];
  290.           zz >>= 1;
  291.         }
  292.         heap[zz] = tmp;
  293.       }
  294.       // assert (nNodes < (MAX_ALPHA_SIZE * 2)) : nNodes;
  295.       for (int i = 1; i <= alphaSize; i++) {
  296.         int j = 0;
  297.         int k = i;
  298.         for (int parent_k; (parent_k = parent[k]) >= 0;) {
  299.           k = parent_k;
  300.           j++;
  301.         }
  302.         len[i - 1] = (char) j;
  303.         if (j > maxLen) {
  304.           tooLong = true;
  305.         }
  306.       }
  307.       if (tooLong) {
  308.         for (int i = 1; i < alphaSize; i++) {
  309.           int j = weight[i] >> 8;
  310.           j = 1 + (j >> 1);
  311.           weight[i] = j << 8;
  312.         }
  313.       }
  314.     }
  315.   }
  316.   private static void hbMakeCodeLengths(final byte[] len, final int[] freq,
  317.       final Data dat, final int alphaSize, final int maxLen) {
  318.     /*
  319.     * Nodes and heap entries run from 1. Entry 0 for both the heap and
  320.     * nodes is a sentinel.
  321.     */
  322.     final int[] heap = dat.heap;
  323.     final int[] weight = dat.weight;
  324.     final int[] parent = dat.parent;
  325.     for (int i = alphaSize; --i >= 0;) {
  326.       weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
  327.     }
  328.     for (boolean tooLong = true; tooLong;) {
  329.       tooLong = false;
  330.       int nNodes = alphaSize;
  331.       int nHeap = 0;
  332.       heap[0] = 0;
  333.       weight[0] = 0;
  334.       parent[0] = -2;
  335.       for (int i = 1; i <= alphaSize; i++) {
  336.         parent[i] = -1;
  337.         nHeap++;
  338.         heap[nHeap] = i;
  339.         int zz = nHeap;
  340.         int tmp = heap[zz];
  341.         while (weight[tmp] < weight[heap[zz >> 1]]) {
  342.           heap[zz] = heap[zz >> 1];
  343.           zz >>= 1;
  344.         }
  345.         heap[zz] = tmp;
  346.       }
  347.       while (nHeap > 1) {
  348.         int n1 = heap[1];
  349.         heap[1] = heap[nHeap];
  350.         nHeap--;
  351.         int yy = 0;
  352.         int zz = 1;
  353.         int tmp = heap[1];
  354.         while (true) {
  355.           yy = zz << 1;
  356.           if (yy > nHeap) {
  357.             break;
  358.           }
  359.           if ((yy < nHeap)
  360.               && (weight[heap[yy + 1]] < weight[heap[yy]])) {
  361.             yy++;
  362.           }
  363.           if (weight[tmp] < weight[heap[yy]]) {
  364.             break;
  365.           }
  366.           heap[zz] = heap[yy];
  367.           zz = yy;
  368.         }
  369.         heap[zz] = tmp;
  370.         int n2 = heap[1];
  371.         heap[1] = heap[nHeap];
  372.         nHeap--;
  373.         yy = 0;
  374.         zz = 1;
  375.         tmp = heap[1];
  376.         while (true) {
  377.           yy = zz << 1;
  378.           if (yy > nHeap) {
  379.             break;
  380.           }
  381.           if ((yy < nHeap)
  382.               && (weight[heap[yy + 1]] < weight[heap[yy]])) {
  383.             yy++;
  384.           }
  385.           if (weight[tmp] < weight[heap[yy]]) {
  386.             break;
  387.           }
  388.           heap[zz] = heap[yy];
  389.           zz = yy;
  390.         }
  391.         heap[zz] = tmp;
  392.         nNodes++;
  393.         parent[n1] = parent[n2] = nNodes;
  394.         final int weight_n1 = weight[n1];
  395.         final int weight_n2 = weight[n2];
  396.         weight[nNodes] = ((weight_n1 & 0xffffff00) + (weight_n2 & 0xffffff00))
  397.             | (1 + (((weight_n1 & 0x000000ff) > (weight_n2 & 0x000000ff)) ? (weight_n1 & 0x000000ff)
  398.                 : (weight_n2 & 0x000000ff)));
  399.         parent[nNodes] = -1;
  400.         nHeap++;
  401.         heap[nHeap] = nNodes;
  402.         tmp = 0;
  403.         zz = nHeap;
  404.         tmp = heap[zz];
  405.         final int weight_tmp = weight[tmp];
  406.         while (weight_tmp < weight[heap[zz >> 1]]) {
  407.           heap[zz] = heap[zz >> 1];
  408.           zz >>= 1;
  409.         }
  410.         heap[zz] = tmp;
  411.       }
  412.       for (int i = 1; i <= alphaSize; i++) {
  413.         int j = 0;
  414.         int k = i;
  415.         for (int parent_k; (parent_k = parent[k]) >= 0;) {
  416.           k = parent_k;
  417.           j++;
  418.         }
  419.         len[i - 1] = (byte) j;
  420.         if (j > maxLen) {
  421.           tooLong = true;
  422.         }
  423.       }
  424.       if (tooLong) {
  425.         for (int i = 1; i < alphaSize; i++) {
  426.           int j = weight[i] >> 8;
  427.           j = 1 + (j >> 1);
  428.           weight[i] = j << 8;
  429.         }
  430.       }
  431.     }
  432.   }
  433.   /**
  434.   * Index of the last char in the block, so the block size == last + 1.
  435.   */
  436.   private int last;
  437.   /**
  438.   * Index in fmap[] of original string after sorting.
  439.   */
  440.   private int origPtr;
  441.   /**
  442.   * Always: in the range 0 .. 9. The current block size is 100000 * this
  443.   * number.
  444.   */
  445.   private final int blockSize100k;
  446.   private boolean blockRandomised;
  447.   private int bsBuff;
  448.   private int bsLive;
  449.   private final CRC crc = new CRC();
  450.   private int nInUse;
  451.   private int nMTF;
  452.   /*
  453.   * Used when sorting. If too many long comparisons happen, we stop sorting,
  454.   * randomise the block slightly, and try again.
  455.   */
  456.   private int workDone;
  457.   private int workLimit;
  458.   private boolean firstAttempt;
  459.   private int currentChar = -1;
  460.   private int runLength = 0;
  461.   private int blockCRC;
  462.   private int combinedCRC;
  463.   private int allowableBlockSize;
  464.   /**
  465.   * All memory intensive stuff.
  466.   */
  467.   private CBZip2OutputStream.Data data;
  468.   private OutputStream out;
  469.   /**
  470.   * Chooses a blocksize based on the given length of the data to compress.
  471.   *
  472.   * @return The blocksize, between {@link #MIN_BLOCKSIZE} and
  473.   *         {@link #MAX_BLOCKSIZE} both inclusive. For a negative
  474.   *         <tt>inputLength</tt> this method returns <tt>MAX_BLOCKSIZE</tt>
  475.   *         always.
  476.   *
  477.   * @param inputLength
  478.   *            The length of the data which will be compressed by
  479.   *            <tt>CBZip2OutputStream</tt>.
  480.   */
  481.   public static int chooseBlockSize(long inputLength) {
  482.     return (inputLength > 0) ? (int) Math
  483.         .min((inputLength / 132000) + 1, 9) : MAX_BLOCKSIZE;
  484.   }
  485.   /**
  486.   * Constructs a new <tt>CBZip2OutputStream</tt> with a blocksize of 900k.
  487.   *
  488.   * <p>
  489.   * <b>Attention: </b>The caller is resonsible to write the two BZip2 magic
  490.   * bytes <tt>"BZ"</tt> to the specified stream prior to calling this
  491.   * constructor.
  492.   * </p>
  493.   *
  494.   * @param out *
  495.   *            the destination stream.
  496.   *
  497.   * @throws IOException
  498.   *             if an I/O error occurs in the specified stream.
  499.   * @throws NullPointerException
  500.   *             if <code>out == null</code>.
  501.   */
  502.   public CBZip2OutputStream(final OutputStream out) throws IOException {
  503.     this(out, MAX_BLOCKSIZE);
  504.   }
  505.   /**
  506.   * Constructs a new <tt>CBZip2OutputStream</tt> with specified blocksize.
  507.   *
  508.   * <p>
  509.   * <b>Attention: </b>The caller is resonsible to write the two BZip2 magic
  510.   * bytes <tt>"BZ"</tt> to the specified stream prior to calling this
  511.   * constructor.
  512.   * </p>
  513.   *
  514.   *
  515.   * @param out
  516.   *            the destination stream.
  517.   * @param blockSize
  518.   *            the blockSize as 100k units.
  519.   *
  520.   * @throws IOException
  521.   *             if an I/O error occurs in the specified stream.
  522.   * @throws IllegalArgumentException
  523.   *             if <code>(blockSize < 1) || (blockSize > 9)</code>.
  524.   * @throws NullPointerException
  525.   *             if <code>out == null</code>.
  526.   *
  527.   * @see #MIN_BLOCKSIZE
  528.   * @see #MAX_BLOCKSIZE
  529.   */
  530.   public CBZip2OutputStream(final OutputStream out, final int blockSize)
  531.       throws IOException {
  532.     super();
  533.     if (blockSize < 1) {
  534.       throw new IllegalArgumentException("blockSize(" + blockSize
  535.           + ") < 1");
  536.     }
  537.     if (blockSize > 9) {
  538.       throw new IllegalArgumentException("blockSize(" + blockSize
  539.           + ") > 9");
  540.     }
  541.     this.blockSize100k = blockSize;
  542.     this.out = out;
  543.     init();
  544.   }
  545.   public void write(final int b) throws IOException {
  546.     if (this.out != null) {
  547.       write0(b);
  548.     } else {
  549.       throw new IOException("closed");
  550.     }
  551.   }
  552.   private void writeRun() throws IOException {
  553.     final int lastShadow = this.last;
  554.     if (lastShadow < this.allowableBlockSize) {
  555.       final int currentCharShadow = this.currentChar;
  556.       final Data dataShadow = this.data;
  557.       dataShadow.inUse[currentCharShadow] = true;
  558.       final byte ch = (byte) currentCharShadow;
  559.       int runLengthShadow = this.runLength;
  560.       this.crc.updateCRC(currentCharShadow, runLengthShadow);
  561.       switch (runLengthShadow) {
  562.       case 1:
  563.         dataShadow.block[lastShadow + 2] = ch;
  564.         this.last = lastShadow + 1;
  565.         break;
  566.       case 2:
  567.         dataShadow.block[lastShadow + 2] = ch;
  568.         dataShadow.block[lastShadow + 3] = ch;
  569.         this.last = lastShadow + 2;
  570.         break;
  571.       case 3: {
  572.         final byte[] block = dataShadow.block;
  573.         block[lastShadow + 2] = ch;
  574.         block[lastShadow + 3] = ch;
  575.         block[lastShadow + 4] = ch;
  576.         this.last = lastShadow + 3;
  577.       }
  578.         break;
  579.       default: {
  580.         runLengthShadow -= 4;
  581.         dataShadow.inUse[runLengthShadow] = true;
  582.         final byte[] block = dataShadow.block;
  583.         block[lastShadow + 2] = ch;
  584.         block[lastShadow + 3] = ch;
  585.         block[lastShadow + 4] = ch;
  586.         block[lastShadow + 5] = ch;
  587.         block[lastShadow + 6] = (byte) runLengthShadow;
  588.         this.last = lastShadow + 5;
  589.       }
  590.         break;
  591.       }
  592.     } else {
  593.       endBlock();
  594.       initBlock();
  595.       writeRun();
  596.     }
  597.   }
  598.   /**
  599.   * Overriden to close the stream.
  600.   */
  601.   protected void finalize() throws Throwable {
  602.     finish();
  603.     super.finalize();
  604.   }
  605.   
  606.   public void finish() throws IOException {
  607.     if (out != null) {
  608.       try {
  609.         if (this.runLength > 0) {
  610.           writeRun();
  611.         }
  612.         this.currentChar = -1;
  613.         endBlock();
  614.         endCompression();
  615.       } finally {
  616.         this.out = null;
  617.         this.data = null;
  618.       }
  619.     }
  620.   }
  621.   public void close() throws IOException {
  622.     if (out != null) {
  623.       OutputStream outShadow = this.out;
  624.       finish();
  625.       outShadow.close();
  626.     }
  627.   }
  628.   
  629.   public void flush() throws IOException {
  630.     OutputStream outShadow = this.out;
  631.     if (outShadow != null) {
  632.       outShadow.flush();
  633.     }
  634.   }
  635.   private void init() throws IOException {
  636.     // write magic: done by caller who created this stream
  637.     // this.out.write('B');
  638.     // this.out.write('Z');
  639.     this.data = new Data(this.blockSize100k);
  640.     /*
  641.     * Write `magic' bytes h indicating file-format == huffmanised, followed
  642.     * by a digit indicating blockSize100k.
  643.     */
  644.     bsPutUByte('h');
  645.     bsPutUByte('0' + this.blockSize100k);
  646.     this.combinedCRC = 0;
  647.     initBlock();
  648.   }
  649.   private void initBlock() {
  650.     // blockNo++;
  651.     this.crc.initialiseCRC();
  652.     this.last = -1;
  653.     // ch = 0;
  654.     boolean[] inUse = this.data.inUse;
  655.     for (int i = 256; --i >= 0;) {
  656.       inUse[i] = false;
  657.     }
  658.     /* 20 is just a paranoia constant */
  659.     this.allowableBlockSize = (this.blockSize100k * BZip2Constants.baseBlockSize) - 20;
  660.   }
  661.   private void endBlock() throws IOException {
  662.     this.blockCRC = this.crc.getFinalCRC();
  663.     this.combinedCRC = (this.combinedCRC << 1) | (this.combinedCRC >>> 31);
  664.     this.combinedCRC ^= this.blockCRC;
  665.     // empty block at end of file
  666.     if (this.last == -1) {
  667.       return;
  668.     }
  669.     /* sort the block and establish posn of original string */
  670.     blockSort();
  671.     /*
  672.     * A 6-byte block header, the value chosen arbitrarily as 0x314159265359
  673.     * :-). A 32 bit value does not really give a strong enough guarantee
  674.     * that the value will not appear by chance in the compressed
  675.     * datastream. Worst-case probability of this event, for a 900k block,
  676.     * is about 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48
  677.     * bits. For a compressed file of size 100Gb -- about 100000 blocks --
  678.     * only a 48-bit marker will do. NB: normal compression/ decompression
  679.     * donot rely on these statistical properties. They are only important
  680.     * when trying to recover blocks from damaged files.
  681.     */
  682.     bsPutUByte(0x31);
  683.     bsPutUByte(0x41);
  684.     bsPutUByte(0x59);
  685.     bsPutUByte(0x26);
  686.     bsPutUByte(0x53);
  687.     bsPutUByte(0x59);
  688.     /* Now the block's CRC, so it is in a known place. */
  689.     bsPutInt(this.blockCRC);
  690.     /* Now a single bit indicating randomisation. */
  691.     if (this.blockRandomised) {
  692.       bsW(1, 1);
  693.     } else {
  694.       bsW(1, 0);
  695.     }
  696.     /* Finally, block's contents proper. */
  697.     moveToFrontCodeAndSend();
  698.   }
  699.   private void endCompression() throws IOException {
  700.     /*
  701.     * Now another magic 48-bit number, 0x177245385090, to indicate the end
  702.     * of the last block. (sqrt(pi), if you want to know. I did want to use
  703.     * e, but it contains too much repetition -- 27 18 28 18 28 46 -- for me
  704.     * to feel statistically comfortable. Call me paranoid.)
  705.     */
  706.     bsPutUByte(0x17);
  707.     bsPutUByte(0x72);
  708.     bsPutUByte(0x45);
  709.     bsPutUByte(0x38);
  710.     bsPutUByte(0x50);
  711.     bsPutUByte(0x90);
  712.     bsPutInt(this.combinedCRC);
  713.     bsFinishedWithStream();
  714.   }
  715.   /**
  716.   * Returns the blocksize parameter specified at construction time.
  717.   */
  718.   public final int getBlockSize() {
  719.     return this.blockSize100k;
  720.   }
  721.   public void write(final byte[] buf, int offs, final int len)
  722.       throws IOException {
  723.     if (offs < 0) {
  724.       throw new IndexOutOfBoundsException("offs(" + offs + ") < 0.");
  725.     }
  726.     if (len < 0) {
  727.       throw new IndexOutOfBoundsException("len(" + len + ") < 0.");
  728.     }
  729.     if (offs + len > buf.length) {
  730.       throw new IndexOutOfBoundsException("offs(" + offs + ") + len("
  731.           + len + ") > buf.length(" + buf.length + ").");
  732.     }
  733.     if (this.out == null) {
  734.       throw new IOException("stream closed");
  735.     }
  736.     for (int hi = offs + len; offs < hi;) {
  737.       write0(buf[offs++]);
  738.     }
  739.   }
  740.   private void write0(int b) throws IOException {
  741.     if (this.currentChar != -1) {
  742.       b &= 0xff;
  743.       if (this.currentChar == b) {
  744.         if (++this.runLength > 254) {
  745.           writeRun();
  746.           this.currentChar = -1;
  747.           this.runLength = 0;
  748.         }
  749.         // else nothing to do
  750.       } else {
  751.         writeRun();
  752.         this.runLength = 1;
  753.         this.currentChar = b;
  754.       }
  755.     } else {
  756.       this.currentChar = b & 0xff;
  757.       this.runLength++;
  758.     }
  759.   }
  760.   private static void hbAssignCodes(final int[] code, final byte[] length,
  761.       final int minLen, final int maxLen, final int alphaSize) {
  762.     int vec = 0;
  763.     for (int n = minLen; n <= maxLen; n++) {
  764.       for (int i = 0; i < alphaSize; i++) {
  765.         if ((length[i] & 0xff) == n) {
  766.           code[i] = vec;
  767.           vec++;
  768.         }
  769.       }
  770.       vec <<= 1;
  771.     }
  772.   }
  773.   private void bsFinishedWithStream() throws IOException {
  774.     while (this.bsLive > 0) {
  775.       int ch = this.bsBuff >> 24;
  776.       this.out.write(ch); // write 8-bit
  777.       this.bsBuff <<= 8;
  778.       this.bsLive -= 8;
  779.     }
  780.   }
  781.   private void bsW(final int n, final int v) throws IOException {
  782.     final OutputStream outShadow = this.out;
  783.     int bsLiveShadow = this.bsLive;
  784.     int bsBuffShadow = this.bsBuff;
  785.     while (bsLiveShadow >= 8) {
  786.       outShadow.write(bsBuffShadow >> 24); // write 8-bit
  787.       bsBuffShadow <<= 8;
  788.       bsLiveShadow -= 8;
  789.     }
  790.     this.bsBuff = bsBuffShadow | (v << (32 - bsLiveShadow - n));
  791.     this.bsLive = bsLiveShadow + n;
  792.   }
  793.   private void bsPutUByte(final int c) throws IOException {
  794.     bsW(8, c);
  795.   }
  796.   private void bsPutInt(final int u) throws IOException {
  797.     bsW(8, (u >> 24) & 0xff);
  798.     bsW(8, (u >> 16) & 0xff);
  799.     bsW(8, (u >> 8) & 0xff);
  800.     bsW(8, u & 0xff);
  801.   }
  802.   private void sendMTFValues() throws IOException {
  803.     final byte[][] len = this.data.sendMTFValues_len;
  804.     final int alphaSize = this.nInUse + 2;
  805.     for (int t = N_GROUPS; --t >= 0;) {
  806.       byte[] len_t = len[t];
  807.       for (int v = alphaSize; --v >= 0;) {
  808.         len_t[v] = GREATER_ICOST;
  809.       }
  810.     }
  811.     /* Decide how many coding tables to use */
  812.     // assert (this.nMTF > 0) : this.nMTF;
  813.     final int nGroups = (this.nMTF < 200) ? 2 : (this.nMTF < 600) ? 3
  814.         : (this.nMTF < 1200) ? 4 : (this.nMTF < 2400) ? 5 : 6;
  815.     /* Generate an initial set of coding tables */
  816.     sendMTFValues0(nGroups, alphaSize);
  817.     /*
  818.     * Iterate up to N_ITERS times to improve the tables.
  819.     */
  820.     final int nSelectors = sendMTFValues1(nGroups, alphaSize);
  821.     /* Compute MTF values for the selectors. */
  822.     sendMTFValues2(nGroups, nSelectors);
  823.     /* Assign actual codes for the tables. */
  824.     sendMTFValues3(nGroups, alphaSize);
  825.     /* Transmit the mapping table. */
  826.     sendMTFValues4();
  827.     /* Now the selectors. */
  828.     sendMTFValues5(nGroups, nSelectors);
  829.     /* Now the coding tables. */
  830.     sendMTFValues6(nGroups, alphaSize);
  831.     /* And finally, the block data proper */
  832.     sendMTFValues7(nSelectors);
  833.   }
  834.   private void sendMTFValues0(final int nGroups, final int alphaSize) {
  835.     final byte[][] len = this.data.sendMTFValues_len;
  836.     final int[] mtfFreq = this.data.mtfFreq;
  837.     int remF = this.nMTF;
  838.     int gs = 0;
  839.     for (int nPart = nGroups; nPart > 0; nPart--) {
  840.       final int tFreq = remF / nPart;
  841.       int ge = gs - 1;
  842.       int aFreq = 0;
  843.       for (final int a = alphaSize - 1; (aFreq < tFreq) && (ge < a);) {
  844.         aFreq += mtfFreq[++ge];
  845.       }
  846.       if ((ge > gs) && (nPart != nGroups) && (nPart != 1)
  847.           && (((nGroups - nPart) & 1) != 0)) {
  848.         aFreq -= mtfFreq[ge--];
  849.       }
  850.       final byte[] len_np = len[nPart - 1];
  851.       for (int v = alphaSize; --v >= 0;) {
  852.         if ((v >= gs) && (v <= ge)) {
  853.           len_np[v] = LESSER_ICOST;
  854.         } else {
  855.           len_np[v] = GREATER_ICOST;
  856.         }
  857.       }
  858.       gs = ge + 1;
  859.       remF -= aFreq;
  860.     }
  861.   }
  862.   private int sendMTFValues1(final int nGroups, final int alphaSize) {
  863.     final Data dataShadow = this.data;
  864.     final int[][] rfreq = dataShadow.sendMTFValues_rfreq;
  865.     final int[] fave = dataShadow.sendMTFValues_fave;
  866.     final short[] cost = dataShadow.sendMTFValues_cost;
  867.     final char[] sfmap = dataShadow.sfmap;
  868.     final byte[] selector = dataShadow.selector;
  869.     final byte[][] len = dataShadow.sendMTFValues_len;
  870.     final byte[] len_0 = len[0];
  871.     final byte[] len_1 = len[1];
  872.     final byte[] len_2 = len[2];
  873.     final byte[] len_3 = len[3];
  874.     final byte[] len_4 = len[4];
  875.     final byte[] len_5 = len[5];
  876.     final int nMTFShadow = this.nMTF;
  877.     int nSelectors = 0;
  878.     for (int iter = 0; iter < N_ITERS; iter++) {
  879.       for (int t = nGroups; --t >= 0;) {
  880.         fave[t] = 0;
  881.         int[] rfreqt = rfreq[t];
  882.         for (int i = alphaSize; --i >= 0;) {
  883.           rfreqt[i] = 0;
  884.         }
  885.       }
  886.       nSelectors = 0;
  887.       for (int gs = 0; gs < this.nMTF;) {
  888.         /* Set group start & end marks. */
  889.         /*
  890.         * Calculate the cost of this group as coded by each of the
  891.         * coding tables.
  892.         */
  893.         final int ge = Math.min(gs + G_SIZE - 1, nMTFShadow - 1);
  894.         if (nGroups == N_GROUPS) {
  895.           // unrolled version of the else-block
  896.           short cost0 = 0;
  897.           short cost1 = 0;
  898.           short cost2 = 0;
  899.           short cost3 = 0;
  900.           short cost4 = 0;
  901.           short cost5 = 0;
  902.           for (int i = gs; i <= ge; i++) {
  903.             final int icv = sfmap[i];
  904.             cost0 += len_0[icv] & 0xff;
  905.             cost1 += len_1[icv] & 0xff;
  906.             cost2 += len_2[icv] & 0xff;
  907.             cost3 += len_3[icv] & 0xff;
  908.             cost4 += len_4[icv] & 0xff;
  909.             cost5 += len_5[icv] & 0xff;
  910.           }
  911.           cost[0] = cost0;
  912.           cost[1] = cost1;
  913.           cost[2] = cost2;
  914.           cost[3] = cost3;
  915.           cost[4] = cost4;
  916.           cost[5] = cost5;
  917.         } else {
  918.           for (int t = nGroups; --t >= 0;) {
  919.             cost[t] = 0;
  920.           }
  921.           for (int i = gs; i <= ge; i++) {
  922.             final int icv = sfmap[i];
  923.             for (int t = nGroups; --t >= 0;) {
  924.               cost[t] += len[t][icv] & 0xff;
  925.             }
  926.           }
  927.         }
  928.         /*
  929.         * Find the coding table which is best for this group, and
  930.         * record its identity in the selector table.
  931.         */
  932.         int bt = -1;
  933.         for (int t = nGroups, bc = 999999999; --t >= 0;) {
  934.           final int cost_t = cost[t];
  935.           if (cost_t < bc) {
  936.             bc = cost_t;
  937.             bt = t;
  938.           }
  939.         }
  940.         fave[bt]++;
  941.         selector[nSelectors] = (byte) bt;
  942.         nSelectors++;
  943.         /*
  944.         * Increment the symbol frequencies for the selected table.
  945.         */
  946.         final int[] rfreq_bt = rfreq[bt];
  947.         for (int i = gs; i <= ge; i++) {
  948.           rfreq_bt[sfmap[i]]++;
  949.         }
  950.         gs = ge + 1;
  951.       }
  952.       /*
  953.       * Recompute the tables based on the accumulated frequencies.
  954.       */
  955.       for (int t = 0; t < nGroups; t++) {
  956.         hbMakeCodeLengths(len[t], rfreq[t], this.data, alphaSize, 20);
  957.       }
  958.     }
  959.     return nSelectors;
  960.   }
  961.   private void sendMTFValues2(final int nGroups, final int nSelectors) {
  962.     // assert (nGroups < 8) : nGroups;
  963.     final Data dataShadow = this.data;
  964.     byte[] pos = dataShadow.sendMTFValues2_pos;
  965.     for (int i = nGroups; --i >= 0;) {
  966.       pos[i] = (byte) i;
  967.     }
  968.     for (int i = 0; i < nSelectors; i++) {
  969.       final byte ll_i = dataShadow.selector[i];
  970.       byte tmp = pos[0];
  971.       int j = 0;
  972.       while (ll_i != tmp) {
  973.         j++;
  974.         byte tmp2 = tmp;
  975.         tmp = pos[j];
  976.         pos[j] = tmp2;
  977.       }
  978.       pos[0] = tmp;
  979.       dataShadow.selectorMtf[i] = (byte) j;
  980.     }
  981.   }
  982.   private void sendMTFValues3(final int nGroups, final int alphaSize) {
  983.     int[][] code = this.data.sendMTFValues_code;
  984.     byte[][] len = this.data.sendMTFValues_len;
  985.     for (int t = 0; t < nGroups; t++) {
  986.       int minLen = 32;
  987.       int maxLen = 0;
  988.       final byte[] len_t = len[t];
  989.       for (int i = alphaSize; --i >= 0;) {
  990.         final int l = len_t[i] & 0xff;
  991.         if (l > maxLen) {
  992.           maxLen = l;
  993.         }
  994.         if (l < minLen) {
  995.           minLen = l;
  996.         }
  997.       }
  998.       // assert (maxLen <= 20) : maxLen;
  999.       // assert (minLen >= 1) : minLen;
  1000.       hbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
  1001.     }
  1002.   }
  1003.   private void sendMTFValues4() throws IOException {
  1004.     final boolean[] inUse = this.data.inUse;
  1005.     final boolean[] inUse16 = this.data.sentMTFValues4_inUse16;
  1006.     for (int i = 16; --i >= 0;) {
  1007.       inUse16[i] = false;
  1008.       final int i16 = i * 16;
  1009.       for (int j = 16; --j >= 0;) {
  1010.         if (inUse[i16 + j]) {
  1011.           inUse16[i] = true;
  1012.         }
  1013.       }
  1014.     }
  1015.     for (int i = 0; i < 16; i++) {
  1016.       bsW(1, inUse16[i] ? 1 : 0);
  1017.     }
  1018.     final OutputStream outShadow = this.out;
  1019.     int bsLiveShadow = this.bsLive;
  1020.     int bsBuffShadow = this.bsBuff;
  1021.     for (int i = 0; i < 16; i++) {
  1022.       if (inUse16[i]) {
  1023.         final int i16 = i * 16;
  1024.         for (int j = 0; j < 16; j++) {
  1025.           // inlined: bsW(1, inUse[i16 + j] ? 1 : 0);
  1026.           while (bsLiveShadow >= 8) {
  1027.             outShadow.write(bsBuffShadow >> 24); // write 8-bit
  1028.             bsBuffShadow <<= 8;
  1029.             bsLiveShadow -= 8;
  1030.           }
  1031.           if (inUse[i16 + j]) {
  1032.             bsBuffShadow |= 1 << (32 - bsLiveShadow - 1);
  1033.           }
  1034.           bsLiveShadow++;
  1035.         }
  1036.       }
  1037.     }
  1038.     this.bsBuff = bsBuffShadow;
  1039.     this.bsLive = bsLiveShadow;
  1040.   }
  1041.   private void sendMTFValues5(final int nGroups, final int nSelectors)
  1042.       throws IOException {
  1043.     bsW(3, nGroups);
  1044.     bsW(15, nSelectors);
  1045.     final OutputStream outShadow = this.out;
  1046.     final byte[] selectorMtf = this.data.selectorMtf;
  1047.     int bsLiveShadow = this.bsLive;
  1048.     int bsBuffShadow = this.bsBuff;
  1049.     for (int i = 0; i < nSelectors; i++) {
  1050.       for (int j = 0, hj = selectorMtf[i] & 0xff; j < hj; j++) {
  1051.         // inlined: bsW(1, 1);
  1052.         while (bsLiveShadow >= 8) {
  1053.           outShadow.write(bsBuffShadow >> 24);
  1054.           bsBuffShadow <<= 8;
  1055.           bsLiveShadow -= 8;
  1056.         }
  1057.         bsBuffShadow |= 1 << (32 - bsLiveShadow - 1);
  1058.         bsLiveShadow++;
  1059.       }
  1060.       // inlined: bsW(1, 0);
  1061.       while (bsLiveShadow >= 8) {
  1062.         outShadow.write(bsBuffShadow >> 24);
  1063.         bsBuffShadow <<= 8;
  1064.         bsLiveShadow -= 8;
  1065.       }
  1066.       // bsBuffShadow |= 0 << (32 - bsLiveShadow - 1);
  1067.       bsLiveShadow++;
  1068.     }
  1069.     this.bsBuff = bsBuffShadow;
  1070.     this.bsLive = bsLiveShadow;
  1071.   }
  1072.   private void sendMTFValues6(final int nGroups, final int alphaSize)
  1073.       throws IOException {
  1074.     final byte[][] len = this.data.sendMTFValues_len;
  1075.     final OutputStream outShadow = this.out;
  1076.     int bsLiveShadow = this.bsLive;
  1077.     int bsBuffShadow = this.bsBuff;
  1078.     for (int t = 0; t < nGroups; t++) {
  1079.       byte[] len_t = len[t];
  1080.       int curr = len_t[0] & 0xff;
  1081.       // inlined: bsW(5, curr);
  1082.       while (bsLiveShadow >= 8) {
  1083.         outShadow.write(bsBuffShadow >> 24); // write 8-bit
  1084.         bsBuffShadow <<= 8;
  1085.         bsLiveShadow -= 8;
  1086.       }
  1087.       bsBuffShadow |= curr << (32 - bsLiveShadow - 5);
  1088.       bsLiveShadow += 5;
  1089.       for (int i = 0; i < alphaSize; i++) {
  1090.         int lti = len_t[i] & 0xff;
  1091.         while (curr < lti) {
  1092.           // inlined: bsW(2, 2);
  1093.           while (bsLiveShadow >= 8) {
  1094.             outShadow.write(bsBuffShadow >> 24); // write 8-bit
  1095.             bsBuffShadow <<= 8;
  1096.             bsLiveShadow -= 8;
  1097.           }
  1098.           bsBuffShadow |= 2 << (32 - bsLiveShadow - 2);
  1099.           bsLiveShadow += 2;
  1100.           curr++; /* 10 */
  1101.         }
  1102.         while (curr > lti) {
  1103.           // inlined: bsW(2, 3);
  1104.           while (bsLiveShadow >= 8) {
  1105.             outShadow.write(bsBuffShadow >> 24); // write 8-bit
  1106.             bsBuffShadow <<= 8;
  1107.             bsLiveShadow -= 8;
  1108.           }
  1109.           bsBuffShadow |= 3 << (32 - bsLiveShadow - 2);
  1110.           bsLiveShadow += 2;
  1111.           curr--; /* 11 */
  1112.         }
  1113.         // inlined: bsW(1, 0);
  1114.         while (bsLiveShadow >= 8) {
  1115.           outShadow.write(bsBuffShadow >> 24); // write 8-bit
  1116.           bsBuffShadow <<= 8;
  1117.           bsLiveShadow -= 8;
  1118.         }
  1119.         // bsBuffShadow |= 0 << (32 - bsLiveShadow - 1);
  1120.         bsLiveShadow++;
  1121.       }
  1122.     }
  1123.     this.bsBuff = bsBuffShadow;
  1124.     this.bsLive = bsLiveShadow;
  1125.   }
  1126.   private void sendMTFValues7(final int nSelectors) throws IOException {
  1127.     final Data dataShadow = this.data;
  1128.     final byte[][] len = dataShadow.sendMTFValues_len;
  1129.     final int[][] code = dataShadow.sendMTFValues_code;
  1130.     final OutputStream outShadow = this.out;
  1131.     final byte[] selector = dataShadow.selector;
  1132.     final char[] sfmap = dataShadow.sfmap;
  1133.     final int nMTFShadow = this.nMTF;
  1134.     int selCtr = 0;
  1135.     int bsLiveShadow = this.bsLive;
  1136.     int bsBuffShadow = this.bsBuff;
  1137.     for (int gs = 0; gs < nMTFShadow;) {
  1138.       final int ge = Math.min(gs + G_SIZE - 1, nMTFShadow - 1);
  1139.       final int selector_selCtr = selector[selCtr] & 0xff;
  1140.       final int[] code_selCtr = code[selector_selCtr];
  1141.       final byte[] len_selCtr = len[selector_selCtr];
  1142.       while (gs <= ge) {
  1143.         final int sfmap_i = sfmap[gs];
  1144.         //
  1145.         // inlined: bsW(len_selCtr[sfmap_i] & 0xff,
  1146.         // code_selCtr[sfmap_i]);
  1147.         //
  1148.         while (bsLiveShadow >= 8) {
  1149.           outShadow.write(bsBuffShadow >> 24);
  1150.           bsBuffShadow <<= 8;
  1151.           bsLiveShadow -= 8;
  1152.         }
  1153.         final int n = len_selCtr[sfmap_i] & 0xFF;
  1154.         bsBuffShadow |= code_selCtr[sfmap_i] << (32 - bsLiveShadow - n);
  1155.         bsLiveShadow += n;
  1156.         gs++;
  1157.       }
  1158.       gs = ge + 1;
  1159.       selCtr++;
  1160.     }
  1161.     this.bsBuff = bsBuffShadow;
  1162.     this.bsLive = bsLiveShadow;
  1163.   }
  1164.   private void moveToFrontCodeAndSend() throws IOException {
  1165.     bsW(24, this.origPtr);
  1166.     generateMTFValues();
  1167.     sendMTFValues();
  1168.   }
  1169.   /**
  1170.   * This is the most hammered method of this class.
  1171.   *
  1172.   * <p>
  1173.   * This is the version using unrolled loops. Normally I never use such ones
  1174.   * in Java code. The unrolling has shown a noticable performance improvement
  1175.   * on JRE 1.4.2 (Linux i586 / HotSpot Client). Of course it depends on the
  1176.   * JIT compiler of the vm.
  1177.   * </p>
  1178.   */
  1179.   private boolean mainSimpleSort(final Data dataShadow, final int lo,
  1180.       final int hi, final int d) {
  1181.     final int bigN = hi - lo + 1;
  1182.     if (bigN < 2) {
  1183.       return this.firstAttempt && (this.workDone > this.workLimit);
  1184.     }
  1185.     int hp = 0;
  1186.     while (INCS[hp] < bigN) {
  1187.       hp++;
  1188.     }
  1189.     final int[] fmap = dataShadow.fmap;
  1190.     final char[] quadrant = dataShadow.quadrant;
  1191.     final byte[] block = dataShadow.block;
  1192.     final int lastShadow = this.last;
  1193.     final int lastPlus1 = lastShadow + 1;
  1194.     final boolean firstAttemptShadow = this.firstAttempt;
  1195.     final int workLimitShadow = this.workLimit;
  1196.     int workDoneShadow = this.workDone;
  1197.     // Following block contains unrolled code which could be shortened by
  1198.     // coding it in additional loops.
  1199.     HP: while (--hp >= 0) {
  1200.       final int h = INCS[hp];
  1201.       final int mj = lo + h - 1;
  1202.       for (int i = lo + h; i <= hi;) {
  1203.         // copy
  1204.         for (int k = 3; (i <= hi) && (--k >= 0); i++) {
  1205.           final int v = fmap[i];
  1206.           final int vd = v + d;
  1207.           int j = i;
  1208.           // for (int a;
  1209.           // (j > mj) && mainGtU((a = fmap[j - h]) + d, vd,
  1210.           // block, quadrant, lastShadow);
  1211.           // j -= h) {
  1212.           // fmap[j] = a;
  1213.           // }
  1214.           //
  1215.           // unrolled version:
  1216.           // start inline mainGTU
  1217.           boolean onceRunned = false;
  1218.           int a = 0;
  1219.           HAMMER: while (true) {
  1220.             if (onceRunned) {
  1221.               fmap[j] = a;
  1222.               if ((j -= h) <= mj) {
  1223.                 break HAMMER;
  1224.               }
  1225.             } else {
  1226.               onceRunned = true;
  1227.             }
  1228.             a = fmap[j - h];
  1229.             int i1 = a + d;
  1230.             int i2 = vd;
  1231.             // following could be done in a loop, but
  1232.             // unrolled it for performance:
  1233.             if (block[i1 + 1] == block[i2 + 1]) {
  1234.               if (block[i1 + 2] == block[i2 + 2]) {
  1235.                 if (block[i1 + 3] == block[i2 + 3]) {
  1236.                   if (block[i1 + 4] == block[i2 + 4]) {
  1237.                     if (block[i1 + 5] == block[i2 + 5]) {
  1238.                       if (block[(i1 += 6)] == block[(i2 += 6)]) {
  1239.                         int x = lastShadow;
  1240.                         X: while (x > 0) {
  1241.                           x -= 4;
  1242.                           if (block[i1 + 1] == block[i2 + 1]) {
  1243.                             if (quadrant[i1] == quadrant[i2]) {
  1244.                               if (block[i1 + 2] == block[i2 + 2]) {
  1245.                                 if (quadrant[i1 + 1] == quadrant[i2 + 1]) {
  1246.                                   if (block[i1 + 3] == block[i2 + 3]) {
  1247.                                     if (quadrant[i1 + 2] == quadrant[i2 + 2]) {
  1248.                                       if (block[i1 + 4] == block[i2 + 4]) {
  1249.                                         if (quadrant[i1 + 3] == quadrant[i2 + 3]) {
  1250.                                           if ((i1 += 4) >= lastPlus1) {
  1251.                                             i1 -= lastPlus1;
  1252.                                           }
  1253.                                           if ((i2 += 4) >= lastPlus1) {
  1254.                                             i2 -= lastPlus1;
  1255.                                           }
  1256.                                           workDoneShadow++;
  1257.                                           continue X;
  1258.                                         } else if ((quadrant[i1 + 3] > quadrant[i2 + 3])) {
  1259.                                           continue HAMMER;
  1260.                                         } else {
  1261.                                           break HAMMER;
  1262.                                         }
  1263.                                       } else if ((block[i1 + 4] & 0xff) > (block[i2 + 4] & 0xff)) {
  1264.                                         continue HAMMER;
  1265.                                       } else {
  1266.                                         break HAMMER;
  1267.                                       }
  1268.                                     } else if ((quadrant[i1 + 2] > quadrant[i2 + 2])) {
  1269.                                       continue HAMMER;
  1270.                                     } else {
  1271.                                       break HAMMER;
  1272.                                     }
  1273.                                   } else if ((block[i1 + 3] & 0xff) > (block[i2 + 3] & 0xff)) {
  1274.                                     continue HAMMER;
  1275.                                   } else {
  1276.                                     break HAMMER;
  1277.                                   }
  1278.                                 } else if ((quadrant[i1 + 1] > quadrant[i2 + 1])) {
  1279.                                   continue HAMMER;
  1280.                                 } else {
  1281.                                   break HAMMER;
  1282.                                 }
  1283.                               } else if ((block[i1 + 2] & 0xff) > (block[i2 + 2] & 0xff)) {
  1284.                                 continue HAMMER;
  1285.                               } else {
  1286.                                 break HAMMER;
  1287.                               }
  1288.                             } else if ((quadrant[i1] > quadrant[i2])) {
  1289.                               continue HAMMER;
  1290.                             } else {
  1291.                               break HAMMER;
  1292.                             }
  1293.                           } else if ((block[i1 + 1] & 0xff) > (block[i2 + 1] & 0xff)) {
  1294.                             continue HAMMER;
  1295.                           } else {
  1296.                             break HAMMER;
  1297.                           }
  1298.                         }
  1299.                         break HAMMER;
  1300.                       } // while x > 0
  1301.                       else {
  1302.                         if ((block[i1] & 0xff) > (block[i2] & 0xff)) {
  1303.                           continue HAMMER;
  1304.                         } else {
  1305.                           break HAMMER;
  1306.                         }
  1307.                       }
  1308.                     } else if ((block[i1 + 5] & 0xff) > (block[i2 + 5] & 0xff)) {
  1309.                       continue HAMMER;
  1310.                     } else {
  1311.                       break HAMMER;
  1312.                     }
  1313.                   } else if ((block[i1 + 4] & 0xff) > (block[i2 + 4] & 0xff)) {
  1314.                     continue HAMMER;
  1315.                   } else {
  1316.                     break HAMMER;
  1317.                   }
  1318.                 } else if ((block[i1 + 3] & 0xff) > (block[i2 + 3] & 0xff)) {
  1319.                   continue HAMMER;
  1320.                 } else {
  1321.                   break HAMMER;
  1322.                 }
  1323.               } else if ((block[i1 + 2] & 0xff) > (block[i2 + 2] & 0xff)) {
  1324.                 continue HAMMER;
  1325.               } else {
  1326.                 break HAMMER;
  1327.               }
  1328.             } else if ((block[i1 + 1] & 0xff) > (block[i2 + 1] & 0xff)) {
  1329.               continue HAMMER;
  1330.             } else {
  1331.               break HAMMER;
  1332.             }
  1333.           } // HAMMER
  1334.           // end inline mainGTU
  1335.           fmap[j] = v;
  1336.         }
  1337.         if (firstAttemptShadow && (i <= hi)
  1338.             && (workDoneShadow > workLimitShadow)) {
  1339.           break HP;
  1340.         }
  1341.       }
  1342.     }
  1343.     this.workDone = workDoneShadow;
  1344.     return firstAttemptShadow && (workDoneShadow > workLimitShadow);
  1345.   }
  1346.   private static void vswap(int[] fmap, int p1, int p2, int n) {
  1347.     n += p1;
  1348.     while (p1 < n) {
  1349.       int t = fmap[p1];
  1350.       fmap[p1++] = fmap[p2];
  1351.       fmap[p2++] = t;
  1352.     }
  1353.   }
  1354.   private static byte med3(byte a, byte b, byte c) {
  1355.     return (a < b) ? (b < c ? b : a < c ? c : a) : (b > c ? b : a > c ? c
  1356.         : a);
  1357.   }
  1358.   private void blockSort() {
  1359.     this.workLimit = WORK_FACTOR * this.last;
  1360.     this.workDone = 0;
  1361.     this.blockRandomised = false;
  1362.     this.firstAttempt = true;
  1363.     mainSort();
  1364.     if (this.firstAttempt && (this.workDone > this.workLimit)) {
  1365.       randomiseBlock();
  1366.       this.workLimit = this.workDone = 0;
  1367.       this.firstAttempt = false;
  1368.       mainSort();
  1369.     }
  1370.     int[] fmap = this.data.fmap;
  1371.     this.origPtr = -1;
  1372.     for (int i = 0, lastShadow = this.last; i <= lastShadow; i++) {
  1373.       if (fmap[i] == 0) {
  1374.         this.origPtr = i;
  1375.         break;
  1376.       }
  1377.     }
  1378.     // assert (this.origPtr != -1) : this.origPtr;
  1379.   }
  1380.   /**
  1381.   * Method "mainQSort3", file "blocksort.c", BZip2 1.0.2
  1382.   */
  1383.   private void mainQSort3(final Data dataShadow, final int loSt,
  1384.       final int hiSt, final int dSt) {
  1385.     final int[] stack_ll = dataShadow.stack_ll;
  1386.     final int[] stack_hh = dataShadow.stack_hh;
  1387.     final int[] stack_dd = dataShadow.stack_dd;
  1388.     final int[] fmap = dataShadow.fmap;
  1389.     final byte[] block = dataShadow.block;
  1390.     stack_ll[0] = loSt;
  1391.     stack_hh[0] = hiSt;
  1392.     stack_dd[0] = dSt;
  1393.     for (int sp = 1; --sp >= 0;) {
  1394.       final int lo = stack_ll[sp];
  1395.       final int hi = stack_hh[sp];
  1396.       final int d = stack_dd[sp];
  1397.       if ((hi - lo < SMALL_THRESH) || (d > DEPTH_THRESH)) {
  1398.         if (mainSimpleSort(dataShadow, lo, hi, d)) {
  1399.           return;
  1400.         }
  1401.       } else {
  1402.         final int d1 = d + 1;
  1403.         final int med = med3(block[fmap[lo] + d1],
  1404.             block[fmap[hi] + d1], block[fmap[(lo + hi) >>> 1] + d1]) & 0xff;
  1405.         int unLo = lo;
  1406.         int unHi = hi;
  1407.         int ltLo = lo;
  1408.         int gtHi = hi;
  1409.         while (true) {
  1410.           while (unLo <= unHi) {
  1411.             final int n = ((int) block[fmap[unLo] + d1] & 0xff)
  1412.                 - med;
  1413.             if (n == 0) {
  1414.               final int temp = fmap[unLo];
  1415.               fmap[unLo++] = fmap[ltLo];
  1416.               fmap[ltLo++] = temp;
  1417.             } else if (n < 0) {
  1418.               unLo++;
  1419.             } else {
  1420.               break;
  1421.             }
  1422.           }
  1423.           while (unLo <= unHi) {
  1424.             final int n = ((int) block[fmap[unHi] + d1] & 0xff)
  1425.                 - med;
  1426.             if (n == 0) {
  1427.               final int temp = fmap[unHi];
  1428.               fmap[unHi--] = fmap[gtHi];
  1429.               fmap[gtHi--] = temp;
  1430.             } else if (n > 0) {
  1431.               unHi--;
  1432.             } else {
  1433.               break;
  1434.             }
  1435.           }
  1436.           if (unLo <= unHi) {
  1437.             final int temp = fmap[unLo];
  1438.             fmap[unLo++] = fmap[unHi];
  1439.             fmap[unHi--] = temp;
  1440.           } else {
  1441.             break;
  1442.           }
  1443.         }
  1444.         if (gtHi < ltLo) {
  1445.           stack_ll[sp] = lo;
  1446.           stack_hh[sp] = hi;
  1447.           stack_dd[sp] = d1;
  1448.           sp++;
  1449.         } else {
  1450.           int n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo)
  1451.               : (unLo - ltLo);
  1452.           vswap(fmap, lo, unLo - n, n);
  1453.           int m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi)
  1454.               : (gtHi - unHi);
  1455.           vswap(fmap, unLo, hi - m + 1, m);
  1456.           n = lo + unLo - ltLo - 1;
  1457.           m = hi - (gtHi - unHi) + 1;
  1458.           stack_ll[sp] = lo;
  1459.           stack_hh[sp] = n;
  1460.           stack_dd[sp] = d;
  1461.           sp++;
  1462.           stack_ll[sp] = n + 1;
  1463.           stack_hh[sp] = m - 1;
  1464.           stack_dd[sp] = d1;
  1465.           sp++;
  1466.           stack_ll[sp] = m;
  1467.           stack_hh[sp] = hi;
  1468.           stack_dd[sp] = d;
  1469.           sp++;
  1470.         }
  1471.       }
  1472.     }
  1473.   }
  1474.   private void mainSort() {
  1475.     final Data dataShadow = this.data;
  1476.     final int[] runningOrder = dataShadow.mainSort_runningOrder;
  1477.     final int[] copy = dataShadow.mainSort_copy;
  1478.     final boolean[] bigDone = dataShadow.mainSort_bigDone;
  1479.     final int[] ftab = dataShadow.ftab;
  1480.     final byte[] block = dataShadow.block;
  1481.     final int[] fmap = dataShadow.fmap;
  1482.     final char[] quadrant = dataShadow.quadrant;
  1483.     final int lastShadow = this.last;
  1484.     final int workLimitShadow = this.workLimit;
  1485.     final boolean firstAttemptShadow = this.firstAttempt;
  1486.     // Set up the 2-byte frequency table
  1487.     for (int i = 65537; --i >= 0;) {
  1488.       ftab[i] = 0;
  1489.     }
  1490.     /*
  1491.     * In the various block-sized structures, live data runs from 0 to
  1492.     * last+NUM_OVERSHOOT_BYTES inclusive. First, set up the overshoot area
  1493.     * for block.
  1494.     */
  1495.     for (int i = 0; i < NUM_OVERSHOOT_BYTES; i++) {
  1496.       block[lastShadow + i + 2] = block[(i % (lastShadow + 1)) + 1];
  1497.     }
  1498.     for (int i = lastShadow + NUM_OVERSHOOT_BYTES +1; --i >= 0;) {
  1499.       quadrant[i] = 0;
  1500.     }
  1501.     block[0] = block[lastShadow + 1];
  1502.     // Complete the initial radix sort:
  1503.     int c1 = block[0] & 0xff;
  1504.     for (int i = 0; i <= lastShadow; i++) {
  1505.       final int c2 = block[i + 1] & 0xff;
  1506.       ftab[(c1 << 8) + c2]++;
  1507.       c1 = c2;
  1508.     }
  1509.     for (int i = 1; i <= 65536; i++)
  1510.       ftab[i] += ftab[i - 1];
  1511.     c1 = block[1] & 0xff;
  1512.     for (int i = 0; i < lastShadow; i++) {
  1513.       final int c2 = block[i + 2] & 0xff;
  1514.       fmap[--ftab[(c1 << 8) + c2]] = i;
  1515.       c1 = c2;
  1516.     }
  1517.     fmap[--ftab[((block[lastShadow + 1] & 0xff) << 8) + (block[1] & 0xff)]] = lastShadow;
  1518.     /*
  1519.     * Now ftab contains the first loc of every small bucket. Calculate the
  1520.     * running order, from smallest to largest big bucket.
  1521.     */
  1522.     for (int i = 256; --i >= 0;) {
  1523.       bigDone[i] = false;
  1524.       runningOrder[i] = i;
  1525.     }
  1526.     for (int h = 364; h != 1;) {
  1527.       h /= 3;
  1528.       for (int i = h; i <= 255; i++) {
  1529.         final int vv = runningOrder[i];
  1530.         final int a = ftab[(vv + 1) << 8] - ftab[vv << 8];
  1531.         final int b = h - 1;
  1532.         int j = i;
  1533.         for (int ro = runningOrder[j - h]; (ftab[(ro + 1) << 8] - ftab[ro << 8]) > a; ro = runningOrder[j
  1534.             - h]) {
  1535.           runningOrder[j] = ro;
  1536.           j -= h;
  1537.           if (j <= b) {
  1538.             break;
  1539.           }
  1540.         }
  1541.         runningOrder[j] = vv;
  1542.       }
  1543.     }
  1544.     /*
  1545.     * The main sorting loop.
  1546.     */
  1547.     for (int i = 0; i <= 255; i++) {
  1548.       /*
  1549.       * Process big buckets, starting with the least full.
  1550.       */
  1551.       final int ss = runningOrder[i];
  1552.       // Step 1:
  1553.       /*
  1554.       * Complete the big bucket [ss] by quicksorting any unsorted small
  1555.       * buckets [ss, j]. Hopefully previous pointer-scanning phases have
  1556.       * already completed many of the small buckets [ss, j], so we don't
  1557.       * have to sort them at all.
  1558.       */
  1559.       for (int j = 0; j <= 255; j++) {
  1560.         final int sb = (ss << 8) + j;
  1561.         final int ftab_sb = ftab[sb];
  1562.         if ((ftab_sb & SETMASK) != SETMASK) {
  1563.           final int lo = ftab_sb & CLEARMASK;
  1564.           final int hi = (ftab[sb + 1] & CLEARMASK) - 1;
  1565.           if (hi > lo) {
  1566.             mainQSort3(dataShadow, lo, hi, 2);
  1567.             if (firstAttemptShadow
  1568.                 && (this.workDone > workLimitShadow)) {
  1569.               return;
  1570.             }
  1571.           }
  1572.           ftab[sb] = ftab_sb | SETMASK;
  1573.         }
  1574.       }
  1575.       // Step 2:
  1576.       // Now scan this big bucket so as to synthesise the
  1577.       // sorted order for small buckets [t, ss] for all t != ss.
  1578.       for (int j = 0; j <= 255; j++) {
  1579.         copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
  1580.       }
  1581.       for (int j = ftab[ss << 8] & CLEARMASK, hj = (ftab[(ss + 1) << 8] & CLEARMASK); j < hj; j++) {
  1582.         final int fmap_j = fmap[j];
  1583.         c1 = block[fmap_j] & 0xff;
  1584.         if (!bigDone[c1]) {
  1585.           fmap[copy[c1]] = (fmap_j == 0) ? lastShadow : (fmap_j - 1);
  1586.           copy[c1]++;
  1587.         }
  1588.       }
  1589.       for (int j = 256; --j >= 0;)
  1590.         ftab[(j << 8) + ss] |= SETMASK;
  1591.       // Step 3:
  1592.       /*
  1593.       * The ss big bucket is now done. Record this fact, and update the
  1594.       * quadrant descriptors. Remember to update quadrants in the
  1595.       * overshoot area too, if necessary. The "if (i < 255)" test merely
  1596.       * skips this updating for the last bucket processed, since updating
  1597.       * for the last bucket is pointless.
  1598.       */
  1599.       bigDone[ss] = true;
  1600.       if (i < 255) {
  1601.         final int bbStart = ftab[ss << 8] & CLEARMASK;
  1602.         final int bbSize = (ftab[(ss + 1) << 8] & CLEARMASK) - bbStart;
  1603.         int shifts = 0;
  1604.         while ((bbSize >> shifts) > 65534) {
  1605.           shifts++;
  1606.         }
  1607.         for (int j = 0; j < bbSize; j++) {
  1608.           final int a2update = fmap[bbStart + j];
  1609.           final char qVal = (char) (j >> shifts);
  1610.           quadrant[a2update] = qVal;
  1611.           if (a2update < NUM_OVERSHOOT_BYTES) {
  1612.             quadrant[a2update + lastShadow + 1] = qVal;
  1613.           }
  1614.         }
  1615.       }
  1616.     }
  1617.   }
  1618.   private void randomiseBlock() {
  1619.     final boolean[] inUse = this.data.inUse;
  1620.     final byte[] block = this.data.block;
  1621.     final int lastShadow = this.last;
  1622.     for (int i = 256; --i >= 0;)
  1623.       inUse[i] = false;
  1624.     int rNToGo = 0;
  1625.     int rTPos = 0;
  1626.     for (int i = 0, j = 1; i <= lastShadow; i = j, j++) {
  1627.       if (rNToGo == 0) {
  1628.         rNToGo = (char) BZip2Constants.rNums[rTPos];
  1629.         if (++rTPos == 512) {
  1630.           rTPos = 0;
  1631.         }
  1632.       }
  1633.       rNToGo--;
  1634.       block[j] ^= ((rNToGo == 1) ? 1 : 0);
  1635.       // handle 16 bit signed numbers
  1636.       inUse[block[j] & 0xff] = true;
  1637.     }
  1638.     this.blockRandomised = true;
  1639.   }
  1640.   private void generateMTFValues() {
  1641.     final int lastShadow = this.last;
  1642.     final Data dataShadow = this.data;
  1643.     final boolean[] inUse = dataShadow.inUse;
  1644.     final byte[] block = dataShadow.block;
  1645.     final int[] fmap = dataShadow.fmap;
  1646.     final char[] sfmap = dataShadow.sfmap;
  1647.     final int[] mtfFreq = dataShadow.mtfFreq;
  1648.     final byte[] unseqToSeq = dataShadow.unseqToSeq;
  1649.     final byte[] yy = dataShadow.generateMTFValues_yy;
  1650.     // make maps
  1651.     int nInUseShadow = 0;
  1652.     for (int i = 0; i < 256; i++) {
  1653.       if (inUse[i]) {
  1654.         unseqToSeq[i] = (byte) nInUseShadow;
  1655.         nInUseShadow++;
  1656.       }
  1657.     }
  1658.     this.nInUse = nInUseShadow;
  1659.     final int eob = nInUseShadow + 1;
  1660.     for (int i = eob; i >= 0; i--) {
  1661.       mtfFreq[i] = 0;
  1662.     }
  1663.     for (int i = nInUseShadow; --i >= 0;) {
  1664.       yy[i] = (byte) i;
  1665.     }
  1666.     int wr = 0;
  1667.     int zPend = 0;
  1668.     for (int i = 0; i <= lastShadow; i++) {
  1669.       final byte ll_i = unseqToSeq[block[fmap[i]] & 0xff];
  1670.       byte tmp = yy[0];
  1671.       int j = 0;
  1672.       while (ll_i != tmp) {
  1673.         j++;
  1674.         byte tmp2 = tmp;
  1675.         tmp = yy[j];
  1676.         yy[j] = tmp2;
  1677.       }
  1678.       yy[0] = tmp;
  1679.       if (j == 0) {
  1680.         zPend++;
  1681.       } else {
  1682.         if (zPend > 0) {
  1683.           zPend--;
  1684.           while (true) {
  1685.             if ((zPend & 1) == 0) {
  1686.               sfmap[wr] = RUNA;
  1687.               wr++;
  1688.               mtfFreq[RUNA]++;
  1689.             } else {
  1690.               sfmap[wr] = RUNB;
  1691.               wr++;
  1692.               mtfFreq[RUNB]++;
  1693.             }
  1694.             if (zPend >= 2) {
  1695.               zPend = (zPend - 2) >> 1;
  1696.             } else {
  1697.               break;
  1698.             }
  1699.           }
  1700.           zPend = 0;
  1701.         }
  1702.         sfmap[wr] = (char) (j + 1);
  1703.         wr++;
  1704.         mtfFreq[j + 1]++;
  1705.       }
  1706.     }
  1707.     if (zPend > 0) {
  1708.       zPend--;
  1709.       while (true) {
  1710.         if ((zPend & 1) == 0) {
  1711.           sfmap[wr] = RUNA;
  1712.           wr++;
  1713.           mtfFreq[RUNA]++;
  1714.         } else {
  1715.           sfmap[wr] = RUNB;
  1716.           wr++;
  1717.           mtfFreq[RUNB]++;
  1718.         }
  1719.         if (zPend >= 2) {
  1720.           zPend = (zPend - 2) >> 1;
  1721.         } else {
  1722.           break;
  1723.         }
  1724.       }
  1725.     }
  1726.     sfmap[wr] = (char) eob;
  1727.     mtfFreq[eob]++;
  1728.     this.nMTF = wr + 1;
  1729.   }
  1730.   private static final class Data extends Object {
  1731.     // with blockSize 900k
  1732.     final boolean[] inUse = new boolean[256]; // 256 byte
  1733.     final byte[] unseqToSeq = new byte[256]; // 256 byte
  1734.     final int[] mtfFreq = new int[MAX_ALPHA_SIZE]; // 1032 byte
  1735.     final byte[] selector = new byte[MAX_SELECTORS]; // 18002 byte
  1736.     final byte[] selectorMtf = new byte[MAX_SELECTORS]; // 18002 byte
  1737.     final byte[] generateMTFValues_yy = new byte[256]; // 256 byte
  1738.     final byte[][] sendMTFValues_len = new byte[N_GROUPS][MAX_ALPHA_SIZE]; // 1548
  1739.     // byte
  1740.     final int[][] sendMTFValues_rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192
  1741.     // byte
  1742.     final int[] sendMTFValues_fave = new int[N_GROUPS]; // 24 byte
  1743.     final short[] sendMTFValues_cost = new short[N_GROUPS]; // 12 byte
  1744.     final int[][] sendMTFValues_code = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192
  1745.     // byte
  1746.     final byte[] sendMTFValues2_pos = new byte[N_GROUPS]; // 6 byte
  1747.     final boolean[] sentMTFValues4_inUse16 = new boolean[16]; // 16 byte
  1748.     final int[] stack_ll = new int[QSORT_STACK_SIZE]; // 4000 byte
  1749.     final int[] stack_hh = new int[QSORT_STACK_SIZE]; // 4000 byte
  1750.     final int[] stack_dd = new int[QSORT_STACK_SIZE]; // 4000 byte
  1751.     final int[] mainSort_runningOrder = new int[256]; // 1024 byte
  1752.     final int[] mainSort_copy = new int[256]; // 1024 byte
  1753.     final boolean[] mainSort_bigDone = new boolean[256]; // 256 byte
  1754.     final int[] heap = new int[MAX_ALPHA_SIZE + 2]; // 1040 byte
  1755.     final int[] weight = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte
  1756.     final int[] parent = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte
  1757.     final int[] ftab = new int[65537]; // 262148 byte
  1758.     // ------------
  1759.     // 333408 byte
  1760.     final byte[] block; // 900021 byte
  1761.     final int[] fmap; // 3600000 byte
  1762.     final char[] sfmap; // 3600000 byte
  1763.     // ------------
  1764.     // 8433529 byte
  1765.     // ============
  1766.     /**
  1767.     * Array instance identical to sfmap, both are used only temporarily and
  1768.     * indepently, so we do not need to allocate additional memory.
  1769.     */
  1770.     final char[] quadrant;
  1771.     Data(int blockSize100k) {
  1772.       super();
  1773.       final int n = blockSize100k * BZip2Constants.baseBlockSize;
  1774.       this.block = new byte[(n + 1 + NUM_OVERSHOOT_BYTES)];
  1775.       this.fmap = new int[n];
  1776.       this.sfmap = new char[2 * n];
  1777.       this.quadrant = this.sfmap;
  1778.     }
  1779.   }
  1780. }