Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsliebig2007-11-06 14:40:03 +0000
committersliebig2007-11-06 14:40:03 +0000
commite8fda18fa74ad3f4a5d042aa1f900069b8aed69e (patch)
tree4017bdde96943125fe7347a38da462813b1d0618 /bundles/ie.wombat.jbdiff
parent2badfd3121cad9b9859a3287cc08b9b4cd07ba93 (diff)
downloadrt.equinox.p2-e8fda18fa74ad3f4a5d042aa1f900069b8aed69e.tar.gz
rt.equinox.p2-e8fda18fa74ad3f4a5d042aa1f900069b8aed69e.tar.xz
rt.equinox.p2-e8fda18fa74ad3f4a5d042aa1f900069b8aed69e.zip
included Bzip2
Diffstat (limited to 'bundles/ie.wombat.jbdiff')
-rw-r--r--bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF3
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/README.txt (renamed from bundles/ie.wombat.jbdiff/src/README.txt)0
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/bsd-license.txt (renamed from bundles/ie.wombat.jbdiff/src/bsd-license.txt)0
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/readme-more.txt (renamed from bundles/ie.wombat.jbdiff/src/readme-more.txt)0
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/BZip2Constants.java73
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2InputStream.java953
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2OutputStream.java2054
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CRC.java94
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/LICENSE203
-rw-r--r--bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/readme-more.txt56
10 files changed, 3435 insertions, 1 deletions
diff --git a/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF b/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF
index 53b210470..6c4300d92 100644
--- a/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF
+++ b/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF
@@ -7,6 +7,7 @@ Bundle-Activator: ie.wombat.jbdiff.Activator
Import-Package: org.osgi.framework;version="1.3.0"
Eclipse-LazyStart: true
Require-Bundle: org.apache.tools.bzip2
-Export-Package: ie.wombat.jbdiff
+Export-Package: ie.wombat.jbdiff,
+ org.apache.tools.bzip2
Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,
J2SE-1.4
diff --git a/bundles/ie.wombat.jbdiff/src/README.txt b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/README.txt
index 30ce0658e..30ce0658e 100644
--- a/bundles/ie.wombat.jbdiff/src/README.txt
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/README.txt
diff --git a/bundles/ie.wombat.jbdiff/src/bsd-license.txt b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/bsd-license.txt
index f94a2fd82..f94a2fd82 100644
--- a/bundles/ie.wombat.jbdiff/src/bsd-license.txt
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/bsd-license.txt
diff --git a/bundles/ie.wombat.jbdiff/src/readme-more.txt b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/readme-more.txt
index 4ab91b992..4ab91b992 100644
--- a/bundles/ie.wombat.jbdiff/src/readme-more.txt
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/readme-more.txt
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/BZip2Constants.java b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/BZip2Constants.java
new file mode 100644
index 000000000..0dbba0b14
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/BZip2Constants.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.apache.tools.bzip2;
+
+/**
+ * Base class for both the compress and decompress classes.
+ * Holds common arrays, and static data.
+ * <p>
+ * This interface is public for historical purposes.
+ * You should have no need to use it.
+ * </p>
+ */
+public interface BZip2Constants {
+
+ int baseBlockSize = 100000;
+ int MAX_ALPHA_SIZE = 258;
+ int MAX_CODE_LEN = 23;
+ int RUNA = 0;
+ int RUNB = 1;
+ int N_GROUPS = 6;
+ int G_SIZE = 50;
+ int N_ITERS = 4;
+ int MAX_SELECTORS = ( 2 + ( 900000 / G_SIZE ) );
+ int NUM_OVERSHOOT_BYTES = 20;
+
+ /**
+ * This array really shouldn't be here.
+ * Again, for historical purposes it is.
+ *
+ * <p>FIXME: This array should be in a private or package private
+ * location, since it could be modified by malicious code.</p>
+ */
+ int[] rNums = { 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, 73, 654,
+ 730, 472, 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591,
+ 733, 623, 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249,
+ 445, 515, 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867,
+ 600, 782, 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686,
+ 600, 224, 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 715, 67, 618, 276, 204, 918, 873, 777,
+ 604, 560, 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820,
+ 908, 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+ 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+ 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+ 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+ 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+ 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 140,
+ 206, 73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 804,
+ 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 768,
+ 550, 608, 933, 378, 286, 215, 979, 792, 961, 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 780,
+ 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 936,
+ 638 };
+}
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2InputStream.java b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2InputStream.java
new file mode 100644
index 000000000..2881a81fa
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2InputStream.java
@@ -0,0 +1,953 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+package org.apache.tools.bzip2;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An input stream that decompresses from the BZip2 format (without the file
+ * header chars) to be read as any other stream.
+ *
+ * <p>The decompression requires large amounts of memory. Thus you
+ * should call the {@link #close() close()} method as soon as
+ * possible, to force <tt>CBZip2InputStream</tt> to release the
+ * allocated memory. See {@link CBZip2OutputStream
+ * CBZip2OutputStream} for information about memory usage.</p>
+ *
+ * <p><tt>CBZip2InputStream</tt> reads bytes from the compressed
+ * source stream via the single byte {@link java.io.InputStream#read()
+ * read()} method exclusively. Thus you should consider to use a
+ * buffered source stream.</p>
+ *
+ * <p>Instances of this class are not threadsafe.</p>
+ */
+public class CBZip2InputStream extends InputStream implements BZip2Constants {
+
+ private static void reportCRCError() throws IOException {
+ // The clean way would be to throw an exception.
+ //throw new IOException("crc error");
+
+ // Just print a message, like the previous versions of this class did
+ System.err.println( "BZip2 CRC error" );
+ }
+
+ private void makeMaps() {
+ final boolean[] inUse = this.data.inUse;
+ final byte[] seqToUnseq = this.data.seqToUnseq;
+
+ int nInUseShadow = 0;
+
+ for ( int i = 0; i < 256; i++ ) {
+ if ( inUse[i] )
+ seqToUnseq[nInUseShadow++] = (byte) i;
+ }
+
+ this.nInUse = nInUseShadow;
+ }
+
+ /**
+ * Index of the last char in the block, so the block size == last + 1.
+ */
+ private int last;
+
+ /**
+ * Index in zptr[] of original string after sorting.
+ */
+ private int origPtr;
+
+ /**
+ * always: in the range 0 .. 9.
+ * The current block size is 100000 * this number.
+ */
+ private int blockSize100k;
+
+ private boolean blockRandomised;
+
+ private int bsBuff;
+ private int bsLive;
+ private final CRC crc = new CRC();
+
+ private int nInUse;
+
+ private InputStream in;
+
+ private int currentChar = -1;
+
+ private static final int EOF = 0;
+ private static final int START_BLOCK_STATE = 1;
+ private static final int RAND_PART_A_STATE = 2;
+ private static final int RAND_PART_B_STATE = 3;
+ private static final int RAND_PART_C_STATE = 4;
+ private static final int NO_RAND_PART_A_STATE = 5;
+ private static final int NO_RAND_PART_B_STATE = 6;
+ private static final int NO_RAND_PART_C_STATE = 7;
+
+ private int currentState = START_BLOCK_STATE;
+
+ private int storedBlockCRC, storedCombinedCRC;
+ private int computedBlockCRC, computedCombinedCRC;
+
+ // Variables used by setup* methods exclusively
+
+ private int su_count;
+ private int su_ch2;
+ private int su_chPrev;
+ private int su_i2;
+ private int su_j2;
+ private int su_rNToGo;
+ private int su_rTPos;
+ private int su_tPos;
+ private char su_z;
+
+ /**
+ * All memory intensive stuff.
+ * This field is initialized by initBlock().
+ */
+ private CBZip2InputStream.Data data;
+
+ /**
+ * Constructs a new CBZip2InputStream which decompresses bytes read from
+ * the specified stream.
+ *
+ * <p>Although BZip2 headers are marked with the magic
+ * <tt>"Bz"</tt> this constructor expects the next byte in the
+ * stream to be the first one after the magic. Thus callers have
+ * to skip the first two bytes. Otherwise this constructor will
+ * throw an exception. </p>
+ *
+ * @throws IOException
+ * if the stream content is malformed or an I/O error occurs.
+ * @throws NullPointerException
+ * if <tt>in == null</tt>
+ */
+ public CBZip2InputStream( final InputStream in ) throws IOException {
+ super();
+
+ this.in = in;
+ init();
+ }
+
+ public int read() throws IOException {
+ if ( this.in != null ) {
+ return read0();
+ } else {
+ throw new IOException( "stream closed" );
+ }
+ }
+
+ public int read( final byte[] dest, final int offs, final int len ) throws IOException {
+ if ( offs < 0 ) {
+ throw new IndexOutOfBoundsException( "offs(" + offs + ") < 0." );
+ }
+ if ( len < 0 ) {
+ throw new IndexOutOfBoundsException( "len(" + len + ") < 0." );
+ }
+ if ( offs + len > dest.length ) {
+ throw new IndexOutOfBoundsException( "offs(" + offs + ") + len(" + len + ") > dest.length(" + dest.length + ")." );
+ }
+ if ( this.in == null ) {
+ throw new IOException( "stream closed" );
+ }
+
+ final int hi = offs + len;
+ int destOffs = offs;
+ for ( int b; ( destOffs < hi ) && ( ( b = read0() ) >= 0 ); ) {
+ dest[destOffs++] = (byte) b;
+ }
+
+ return ( destOffs == offs ) ? -1 : ( destOffs - offs );
+ }
+
+ private int read0() throws IOException {
+ final int retChar = this.currentChar;
+
+ switch ( this.currentState ) {
+ case EOF:
+ return -1;
+
+ case START_BLOCK_STATE:
+ throw new IllegalStateException();
+
+ case RAND_PART_A_STATE:
+ throw new IllegalStateException();
+
+ case RAND_PART_B_STATE:
+ setupRandPartB();
+ break;
+
+ case RAND_PART_C_STATE:
+ setupRandPartC();
+ break;
+
+ case NO_RAND_PART_A_STATE:
+ throw new IllegalStateException();
+
+ case NO_RAND_PART_B_STATE:
+ setupNoRandPartB();
+ break;
+
+ case NO_RAND_PART_C_STATE:
+ setupNoRandPartC();
+ break;
+
+ default:
+ throw new IllegalStateException();
+ }
+
+ return retChar;
+ }
+
+ private void init() throws IOException {
+ int magic2 = this.in.read();
+ if ( magic2 != 'h' ) {
+ throw new IOException( "Stream is not BZip2 formatted: expected 'h'" + " as first byte but got '" + (char) magic2 + "'" );
+ }
+
+ int blockSize = this.in.read();
+ if ( ( blockSize < '1' ) || ( blockSize > '9' ) ) {
+ throw new IOException( "Stream is not BZip2 formatted: illegal " + "blocksize " + (char) blockSize );
+ }
+
+ this.blockSize100k = blockSize - '0';
+
+ initBlock();
+ setupBlock();
+ }
+
+ private void initBlock() throws IOException {
+ char magic0 = bsGetUByte();
+ char magic1 = bsGetUByte();
+ char magic2 = bsGetUByte();
+ char magic3 = bsGetUByte();
+ char magic4 = bsGetUByte();
+ char magic5 = bsGetUByte();
+
+ if ( magic0 == 0x17 && magic1 == 0x72 && magic2 == 0x45 && magic3 == 0x38 && magic4 == 0x50 && magic5 == 0x90 ) {
+ complete(); // end of file
+ } else if ( magic0 != 0x31 || // '1'
+ magic1 != 0x41 || // ')'
+ magic2 != 0x59 || // 'Y'
+ magic3 != 0x26 || // '&'
+ magic4 != 0x53 || // 'S'
+ magic5 != 0x59 // 'Y'
+ ) {
+ this.currentState = EOF;
+ throw new IOException( "bad block header" );
+ } else {
+ this.storedBlockCRC = bsGetInt();
+ this.blockRandomised = bsR( 1 ) == 1;
+
+ /**
+ * Allocate data here instead in constructor, so we do not
+ * allocate it if the input file is empty.
+ */
+ if ( this.data == null ) {
+ this.data = new Data( this.blockSize100k );
+ }
+
+ // currBlockNo++;
+ getAndMoveToFrontDecode();
+
+ this.crc.initialiseCRC();
+ this.currentState = START_BLOCK_STATE;
+ }
+ }
+
+ private void endBlock() throws IOException {
+ this.computedBlockCRC = this.crc.getFinalCRC();
+
+ // A bad CRC is considered a fatal error.
+ if ( this.storedBlockCRC != this.computedBlockCRC ) {
+ // make next blocks readable without error
+ // (repair feature, not yet documented, not tested)
+ this.computedCombinedCRC = ( this.storedCombinedCRC << 1 ) | ( this.storedCombinedCRC >>> 31 );
+ this.computedCombinedCRC ^= this.storedBlockCRC;
+
+ reportCRCError();
+ }
+
+ this.computedCombinedCRC = ( this.computedCombinedCRC << 1 ) | ( this.computedCombinedCRC >>> 31 );
+ this.computedCombinedCRC ^= this.computedBlockCRC;
+ }
+
+ private void complete() throws IOException {
+ this.storedCombinedCRC = bsGetInt();
+ this.currentState = EOF;
+ this.data = null;
+
+ if ( this.storedCombinedCRC != this.computedCombinedCRC ) {
+ reportCRCError();
+ }
+ }
+
+ public void close() throws IOException {
+ InputStream inShadow = this.in;
+ if ( inShadow != null ) {
+ try {
+ if ( inShadow != System.in ) {
+ inShadow.close();
+ }
+ } finally {
+ this.data = null;
+ this.in = null;
+ }
+ }
+ }
+
+ private int bsR( final int n ) throws IOException {
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ if ( bsLiveShadow < n ) {
+ final InputStream inShadow = this.in;
+ do {
+ int thech = inShadow.read();
+
+ if ( thech < 0 ) {
+ throw new IOException( "unexpected end of stream" );
+ }
+
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ } while ( bsLiveShadow < n );
+
+ this.bsBuff = bsBuffShadow;
+ }
+
+ this.bsLive = bsLiveShadow - n;
+ return ( bsBuffShadow >> ( bsLiveShadow - n ) ) & ( ( 1 << n ) - 1 );
+ }
+
+ private boolean bsGetBit() throws IOException {
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ if ( bsLiveShadow < 1 ) {
+ int thech = this.in.read();
+
+ if ( thech < 0 ) {
+ throw new IOException( "unexpected end of stream" );
+ }
+
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ this.bsBuff = bsBuffShadow;
+ }
+
+ this.bsLive = bsLiveShadow - 1;
+ return ( ( bsBuffShadow >> ( bsLiveShadow - 1 ) ) & 1 ) != 0;
+ }
+
+ private char bsGetUByte() throws IOException {
+ return (char) bsR( 8 );
+ }
+
+ private int bsGetInt() throws IOException {
+ return ( ( ( ( ( bsR( 8 ) << 8 ) | bsR( 8 ) ) << 8 ) | bsR( 8 ) ) << 8 ) | bsR( 8 );
+ }
+
+ /**
+ * Called by createHuffmanDecodingTables() exclusively.
+ */
+ private static void hbCreateDecodeTables( final int[] limit, final int[] base, final int[] perm, final char[] length, final int minLen, final int maxLen,
+ final int alphaSize ) {
+ for ( int i = minLen, pp = 0; i <= maxLen; i++ ) {
+ for ( int j = 0; j < alphaSize; j++ ) {
+ if ( length[j] == i ) {
+ perm[pp++] = j;
+ }
+ }
+ }
+
+ for ( int i = MAX_CODE_LEN; --i > 0; ) {
+ base[i] = 0;
+ limit[i] = 0;
+ }
+
+ for ( int i = 0; i < alphaSize; i++ ) {
+ base[length[i] + 1]++;
+ }
+
+ for ( int i = 1, b = base[0]; i < MAX_CODE_LEN; i++ ) {
+ b += base[i];
+ base[i] = b;
+ }
+
+ for ( int i = minLen, vec = 0, b = base[i]; i <= maxLen; i++ ) {
+ final int nb = base[i + 1];
+ vec += nb - b;
+ b = nb;
+ limit[i] = vec - 1;
+ vec <<= 1;
+ }
+
+ for ( int i = minLen + 1; i <= maxLen; i++ ) {
+ base[i] = ( ( limit[i - 1] + 1 ) << 1 ) - base[i];
+ }
+ }
+
+ private void recvDecodingTables() throws IOException {
+ final Data dataShadow = this.data;
+ final boolean[] inUse = dataShadow.inUse;
+ final byte[] pos = dataShadow.recvDecodingTables_pos;
+ final byte[] selector = dataShadow.selector;
+ final byte[] selectorMtf = dataShadow.selectorMtf;
+
+ int inUse16 = 0;
+
+ /* Receive the mapping table */
+ for ( int i = 0; i < 16; i++ ) {
+ if ( bsGetBit() ) {
+ inUse16 |= 1 << i;
+ }
+ }
+
+ for ( int i = 256; --i >= 0; ) {
+ inUse[i] = false;
+ }
+
+ for ( int i = 0; i < 16; i++ ) {
+ if ( ( inUse16 & ( 1 << i ) ) != 0 ) {
+ final int i16 = i << 4;
+ for ( int j = 0; j < 16; j++ ) {
+ if ( bsGetBit() ) {
+ inUse[i16 + j] = true;
+ }
+ }
+ }
+ }
+
+ makeMaps();
+ final int alphaSize = this.nInUse + 2;
+
+ /* Now the selectors */
+ final int nGroups = bsR( 3 );
+ final int nSelectors = bsR( 15 );
+
+ for ( int i = 0; i < nSelectors; i++ ) {
+ int j = 0;
+ while ( bsGetBit() ) {
+ j++;
+ }
+ selectorMtf[i] = (byte) j;
+ }
+
+ /* Undo the MTF values for the selectors. */
+ for ( int v = nGroups; --v >= 0; ) {
+ pos[v] = (byte) v;
+ }
+
+ for ( int i = 0; i < nSelectors; i++ ) {
+ int v = selectorMtf[i] & 0xff;
+ final byte tmp = pos[v];
+ while ( v > 0 ) {
+ // nearly all times v is zero, 4 in most other cases
+ pos[v] = pos[v - 1];
+ v--;
+ }
+ pos[0] = tmp;
+ selector[i] = tmp;
+ }
+
+ final char[][] len = dataShadow.temp_charArray2d;
+
+ /* Now the coding tables */
+ for ( int t = 0; t < nGroups; t++ ) {
+ int curr = bsR( 5 );
+ final char[] len_t = len[t];
+ for ( int i = 0; i < alphaSize; i++ ) {
+ while ( bsGetBit() ) {
+ curr += bsGetBit() ? -1 : 1;
+ }
+ len_t[i] = (char) curr;
+ }
+ }
+
+ // finally create the Huffman tables
+ createHuffmanDecodingTables( alphaSize, nGroups );
+ }
+
+ /**
+ * Called by recvDecodingTables() exclusively.
+ */
+ private void createHuffmanDecodingTables( final int alphaSize, final int nGroups ) {
+ final Data dataShadow = this.data;
+ final char[][] len = dataShadow.temp_charArray2d;
+ final int[] minLens = dataShadow.minLens;
+ final int[][] limit = dataShadow.limit;
+ final int[][] base = dataShadow.base;
+ final int[][] perm = dataShadow.perm;
+
+ for ( int t = 0; t < nGroups; t++ ) {
+ int minLen = 32;
+ int maxLen = 0;
+ final char[] len_t = len[t];
+ for ( int i = alphaSize; --i >= 0; ) {
+ final char lent = len_t[i];
+ if ( lent > maxLen ) {
+ maxLen = lent;
+ }
+ if ( lent < minLen ) {
+ minLen = lent;
+ }
+ }
+ hbCreateDecodeTables( limit[t], base[t], perm[t], len[t], minLen, maxLen, alphaSize );
+ minLens[t] = minLen;
+ }
+ }
+
+ private void getAndMoveToFrontDecode() throws IOException {
+ this.origPtr = bsR( 24 );
+ recvDecodingTables();
+
+ final InputStream inShadow = this.in;
+ final Data dataShadow = this.data;
+ final byte[] ll8 = dataShadow.ll8;
+ final int[] unzftab = dataShadow.unzftab;
+ final byte[] selector = dataShadow.selector;
+ final byte[] seqToUnseq = dataShadow.seqToUnseq;
+ final char[] yy = dataShadow.getAndMoveToFrontDecode_yy;
+ final int[] minLens = dataShadow.minLens;
+ final int[][] limit = dataShadow.limit;
+ final int[][] base = dataShadow.base;
+ final int[][] perm = dataShadow.perm;
+ final int limitLast = this.blockSize100k * 100000;
+
+ /*
+ Setting up the unzftab entries here is not strictly
+ necessary, but it does save having to do it later
+ in a separate pass, and so saves a block's worth of
+ cache misses.
+ */
+ for ( int i = 256; --i >= 0; ) {
+ yy[i] = (char) i;
+ unzftab[i] = 0;
+ }
+
+ int groupNo = 0;
+ int groupPos = G_SIZE - 1;
+ final int eob = this.nInUse + 1;
+ int nextSym = getAndMoveToFrontDecode0( 0 );
+ int bsBuffShadow = this.bsBuff;
+ int bsLiveShadow = this.bsLive;
+ int lastShadow = -1;
+ int zt = selector[groupNo] & 0xff;
+ int[] base_zt = base[zt];
+ int[] limit_zt = limit[zt];
+ int[] perm_zt = perm[zt];
+ int minLens_zt = minLens[zt];
+
+ while ( nextSym != eob ) {
+ if ( ( nextSym == RUNA ) || ( nextSym == RUNB ) ) {
+ int s = -1;
+
+ for ( int n = 1; true; n <<= 1 ) {
+ if ( nextSym == RUNA ) {
+ s += n;
+ } else if ( nextSym == RUNB ) {
+ s += n << 1;
+ } else {
+ break;
+ }
+
+ if ( groupPos == 0 ) {
+ groupPos = G_SIZE - 1;
+ zt = selector[++groupNo] & 0xff;
+ base_zt = base[zt];
+ limit_zt = limit[zt];
+ perm_zt = perm[zt];
+ minLens_zt = minLens[zt];
+ } else {
+ groupPos--;
+ }
+
+ int zn = minLens_zt;
+
+ // Inlined:
+ // int zvec = bsR(zn);
+ while ( bsLiveShadow < zn ) {
+ final int thech = inShadow.read();
+ if ( thech >= 0 ) {
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ continue;
+ } else {
+ throw new IOException( "unexpected end of stream" );
+ }
+ }
+ int zvec = ( bsBuffShadow >> ( bsLiveShadow - zn ) ) & ( ( 1 << zn ) - 1 );
+ bsLiveShadow -= zn;
+
+ while ( zvec > limit_zt[zn] ) {
+ zn++;
+ while ( bsLiveShadow < 1 ) {
+ final int thech = inShadow.read();
+ if ( thech >= 0 ) {
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ continue;
+ } else {
+ throw new IOException( "unexpected end of stream" );
+ }
+ }
+ bsLiveShadow--;
+ zvec = ( zvec << 1 ) | ( ( bsBuffShadow >> bsLiveShadow ) & 1 );
+ }
+ nextSym = perm_zt[zvec - base_zt[zn]];
+ }
+
+ final byte ch = seqToUnseq[yy[0]];
+ unzftab[ch & 0xff] += s + 1;
+
+ while ( s-- >= 0 ) {
+ ll8[++lastShadow] = ch;
+ }
+
+ if ( lastShadow >= limitLast ) {
+ throw new IOException( "block overrun" );
+ }
+ } else {
+ if ( ++lastShadow >= limitLast ) {
+ throw new IOException( "block overrun" );
+ }
+
+ final char tmp = yy[nextSym - 1];
+ unzftab[seqToUnseq[tmp] & 0xff]++;
+ ll8[lastShadow] = seqToUnseq[tmp];
+
+ /*
+ This loop is hammered during decompression,
+ hence avoid native method call overhead of
+ System.arraycopy for very small ranges to copy.
+ */
+ if ( nextSym <= 16 ) {
+ for ( int j = nextSym - 1; j > 0; ) {
+ yy[j] = yy[--j];
+ }
+ } else {
+ System.arraycopy( yy, 0, yy, 1, nextSym - 1 );
+ }
+
+ yy[0] = tmp;
+
+ if ( groupPos == 0 ) {
+ groupPos = G_SIZE - 1;
+ zt = selector[++groupNo] & 0xff;
+ base_zt = base[zt];
+ limit_zt = limit[zt];
+ perm_zt = perm[zt];
+ minLens_zt = minLens[zt];
+ } else {
+ groupPos--;
+ }
+
+ int zn = minLens_zt;
+
+ // Inlined:
+ // int zvec = bsR(zn);
+ while ( bsLiveShadow < zn ) {
+ final int thech = inShadow.read();
+ if ( thech >= 0 ) {
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ continue;
+ } else {
+ throw new IOException( "unexpected end of stream" );
+ }
+ }
+ int zvec = ( bsBuffShadow >> ( bsLiveShadow - zn ) ) & ( ( 1 << zn ) - 1 );
+ bsLiveShadow -= zn;
+
+ while ( zvec > limit_zt[zn] ) {
+ zn++;
+ while ( bsLiveShadow < 1 ) {
+ final int thech = inShadow.read();
+ if ( thech >= 0 ) {
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ continue;
+ } else {
+ throw new IOException( "unexpected end of stream" );
+ }
+ }
+ bsLiveShadow--;
+ zvec = ( zvec << 1 ) | ( ( bsBuffShadow >> bsLiveShadow ) & 1 );
+ }
+ nextSym = perm_zt[zvec - base_zt[zn]];
+ }
+ }
+
+ this.last = lastShadow;
+ this.bsLive = bsLiveShadow;
+ this.bsBuff = bsBuffShadow;
+ }
+
+ private int getAndMoveToFrontDecode0( final int groupNo ) throws IOException {
+ final InputStream inShadow = this.in;
+ final Data dataShadow = this.data;
+ final int zt = dataShadow.selector[groupNo] & 0xff;
+ final int[] limit_zt = dataShadow.limit[zt];
+ int zn = dataShadow.minLens[zt];
+ int zvec = bsR( zn );
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ while ( zvec > limit_zt[zn] ) {
+ zn++;
+ while ( bsLiveShadow < 1 ) {
+ final int thech = inShadow.read();
+
+ if ( thech >= 0 ) {
+ bsBuffShadow = ( bsBuffShadow << 8 ) | thech;
+ bsLiveShadow += 8;
+ continue;
+ } else {
+ throw new IOException( "unexpected end of stream" );
+ }
+ }
+ bsLiveShadow--;
+ zvec = ( zvec << 1 ) | ( ( bsBuffShadow >> bsLiveShadow ) & 1 );
+ }
+
+ this.bsLive = bsLiveShadow;
+ this.bsBuff = bsBuffShadow;
+
+ return dataShadow.perm[zt][zvec - dataShadow.base[zt][zn]];
+ }
+
+ private void setupBlock() throws IOException {
+ if ( this.data == null ) {
+ return;
+ }
+
+ final int[] cftab = this.data.cftab;
+ final int[] tt = this.data.initTT( this.last + 1 );
+ final byte[] ll8 = this.data.ll8;
+ cftab[0] = 0;
+ System.arraycopy( this.data.unzftab, 0, cftab, 1, 256 );
+
+ for ( int i = 1, c = cftab[0]; i <= 256; i++ ) {
+ c += cftab[i];
+ cftab[i] = c;
+ }
+
+ for ( int i = 0, lastShadow = this.last; i <= lastShadow; i++ ) {
+ tt[cftab[ll8[i] & 0xff]++] = i;
+ }
+
+ if ( ( this.origPtr < 0 ) || ( this.origPtr >= tt.length ) ) {
+ throw new IOException( "stream corrupted" );
+ }
+
+ this.su_tPos = tt[this.origPtr];
+ this.su_count = 0;
+ this.su_i2 = 0;
+ this.su_ch2 = 256; /* not a char and not EOF */
+
+ if ( this.blockRandomised ) {
+ this.su_rNToGo = 0;
+ this.su_rTPos = 0;
+ setupRandPartA();
+ } else {
+ setupNoRandPartA();
+ }
+ }
+
+ private void setupRandPartA() throws IOException {
+ if ( this.su_i2 <= this.last ) {
+ this.su_chPrev = this.su_ch2;
+ int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff;
+ this.su_tPos = this.data.tt[this.su_tPos];
+ if ( this.su_rNToGo == 0 ) {
+ this.su_rNToGo = BZip2Constants.rNums[this.su_rTPos] - 1;
+ if ( ++this.su_rTPos == 512 ) {
+ this.su_rTPos = 0;
+ }
+ } else {
+ this.su_rNToGo--;
+ }
+ this.su_ch2 = su_ch2Shadow ^= ( this.su_rNToGo == 1 ) ? 1 : 0;
+ this.su_i2++;
+ this.currentChar = su_ch2Shadow;
+ this.currentState = RAND_PART_B_STATE;
+ this.crc.updateCRC( su_ch2Shadow );
+ } else {
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupNoRandPartA() throws IOException {
+ if ( this.su_i2 <= this.last ) {
+ this.su_chPrev = this.su_ch2;
+ int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff;
+ this.su_ch2 = su_ch2Shadow;
+ this.su_tPos = this.data.tt[this.su_tPos];
+ this.su_i2++;
+ this.currentChar = su_ch2Shadow;
+ this.currentState = NO_RAND_PART_B_STATE;
+ this.crc.updateCRC( su_ch2Shadow );
+ } else {
+ this.currentState = NO_RAND_PART_A_STATE;
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupRandPartB() throws IOException {
+ if ( this.su_ch2 != this.su_chPrev ) {
+ this.currentState = RAND_PART_A_STATE;
+ this.su_count = 1;
+ setupRandPartA();
+ } else if ( ++this.su_count >= 4 ) {
+ this.su_z = (char) ( this.data.ll8[this.su_tPos] & 0xff );
+ this.su_tPos = this.data.tt[this.su_tPos];
+ if ( this.su_rNToGo == 0 ) {
+ this.su_rNToGo = BZip2Constants.rNums[this.su_rTPos] - 1;
+ if ( ++this.su_rTPos == 512 ) {
+ this.su_rTPos = 0;
+ }
+ } else {
+ this.su_rNToGo--;
+ }
+ this.su_j2 = 0;
+ this.currentState = RAND_PART_C_STATE;
+ if ( this.su_rNToGo == 1 ) {
+ this.su_z ^= 1;
+ }
+ setupRandPartC();
+ } else {
+ this.currentState = RAND_PART_A_STATE;
+ setupRandPartA();
+ }
+ }
+
+ private void setupRandPartC() throws IOException {
+ if ( this.su_j2 < this.su_z ) {
+ this.currentChar = this.su_ch2;
+ this.crc.updateCRC( this.su_ch2 );
+ this.su_j2++;
+ } else {
+ this.currentState = RAND_PART_A_STATE;
+ this.su_i2++;
+ this.su_count = 0;
+ setupRandPartA();
+ }
+ }
+
+ private void setupNoRandPartB() throws IOException {
+ if ( this.su_ch2 != this.su_chPrev ) {
+ this.su_count = 1;
+ setupNoRandPartA();
+ } else if ( ++this.su_count >= 4 ) {
+ this.su_z = (char) ( this.data.ll8[this.su_tPos] & 0xff );
+ this.su_tPos = this.data.tt[this.su_tPos];
+ this.su_j2 = 0;
+ setupNoRandPartC();
+ } else {
+ setupNoRandPartA();
+ }
+ }
+
+ private void setupNoRandPartC() throws IOException {
+ if ( this.su_j2 < this.su_z ) {
+ int su_ch2Shadow = this.su_ch2;
+ this.currentChar = su_ch2Shadow;
+ this.crc.updateCRC( su_ch2Shadow );
+ this.su_j2++;
+ this.currentState = NO_RAND_PART_C_STATE;
+ } else {
+ this.su_i2++;
+ this.su_count = 0;
+ setupNoRandPartA();
+ }
+ }
+
+ private static final class Data extends Object {
+
+ // (with blockSize 900k)
+ final boolean[] inUse = new boolean[256]; // 256 byte
+
+ final byte[] seqToUnseq = new byte[256]; // 256 byte
+ final byte[] selector = new byte[MAX_SELECTORS]; // 18002 byte
+ final byte[] selectorMtf = new byte[MAX_SELECTORS]; // 18002 byte
+
+ /**
+ * Freq table collected to save a pass over the data during
+ * decompression.
+ */
+ final int[] unzftab = new int[256]; // 1024 byte
+
+ final int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192 byte
+ final int[][] base = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192 byte
+ final int[][] perm = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192 byte
+ final int[] minLens = new int[N_GROUPS]; // 24 byte
+
+ final int[] cftab = new int[257]; // 1028 byte
+ final char[] getAndMoveToFrontDecode_yy = new char[256]; // 512 byte
+ final char[][] temp_charArray2d = new char[N_GROUPS][MAX_ALPHA_SIZE]; // 3096 byte
+ final byte[] recvDecodingTables_pos = new byte[N_GROUPS]; // 6 byte
+ //---------------
+ // 60798 byte
+
+ int[] tt; // 3600000 byte
+ byte[] ll8; // 900000 byte
+
+ //---------------
+ // 4560782 byte
+ //===============
+
+ Data( int blockSize100k ) {
+ super();
+
+ this.ll8 = new byte[blockSize100k * BZip2Constants.baseBlockSize];
+ }
+
+ /**
+ * Initializes the {@link #tt} array.
+ *
+ * This method is called when the required length of the array
+ * is known. I don't initialize it at construction time to
+ * avoid unneccessary memory allocation when compressing small
+ * files.
+ */
+ final int[] initTT( int length ) {
+ int[] ttShadow = this.tt;
+
+ // tt.length should always be >= length, but theoretically
+ // it can happen, if the compressor mixed small and large
+ // blocks. Normally only the last block will be smaller
+ // than others.
+ if ( ( ttShadow == null ) || ( ttShadow.length < length ) ) {
+ this.tt = ttShadow = new int[length];
+ }
+
+ return ttShadow;
+ }
+
+ }
+}
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2OutputStream.java b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2OutputStream.java
new file mode 100644
index 000000000..c5f6179f2
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CBZip2OutputStream.java
@@ -0,0 +1,2054 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.apache.tools.bzip2;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An output stream that compresses into the BZip2 format (without the file
+ * header chars) into another stream.
+
+ * <p>The compression requires large amounts of memory. Thus you
+ * should call the {@link #close() close()} method as soon as
+ * possible, to force <tt>CBZip2OutputStream</tt> to release the
+ * allocated memory.</p>
+ *
+ * <p>You can shrink the amount of allocated memory and maybe raise
+ * the compression speed by choosing a lower blocksize, which in turn
+ * may cause a lower compression ratio. You can avoid unnecessary
+ * memory allocation by avoiding using a blocksize which is bigger
+ * than the size of the input. </p>
+ *
+ * <p>You can compute the memory usage for compressing by the
+ * following formula:</p>
+ * <pre>
+ * <code>400k + (9 * blocksize)</code>.
+ * </pre>
+ *
+ * <p>To get the memory required for decompression by {@link
+ * CBZip2InputStream CBZip2InputStream} use</p>
+ * <pre>
+ * <code>65k + (5 * blocksize)</code>.
+ * </pre>
+ *
+ * <table width="100%" border="1">
+ * <colgroup>
+ * <col width="33%" />
+ * <col width="33%" />
+ * <col width="33%" />
+ * </colgroup>
+ * <tr>
+ * <th colspan="3">Memory usage by blocksize</th>
+ * </tr><tr>
+ * <th align="right">Blocksize</th>
+ * <th align="right">Compression<br>memory usage</th>
+ * <th align="right">Decompression<br>memory usage</th>
+ * </tr><tr>
+ * <td align="right">100k</td>
+ * <td align="right">1300k</td>
+ * <td align="right"> 565k</td>
+ * </tr><tr>
+ * <td align="right">200k</td>
+ * <td align="right">2200k</td>
+ * <td align="right">1065k</td>
+ * </tr><tr>
+ * <td align="right">300k</td>
+ * <td align="right">3100k</td>
+ * <td align="right">1565k</td>
+ * </tr><tr>
+ * <td align="right">400k</td>
+ * <td align="right">4000k</td>
+ * <td align="right">2065k</td>
+ * </tr><tr>
+ * <td align="right">500k</td>
+ * <td align="right">4900k</td>
+ * <td align="right">2565k</td>
+ * </tr><tr>
+ * <td align="right">600k</td>
+ * <td align="right">5800k</td>
+ * <td align="right">3065k</td>
+ * </tr><tr>
+ * <td align="right">700k</td>
+ * <td align="right">6700k</td>
+ * <td align="right">3565k</td>
+ * </tr><tr>
+ * <td align="right">800k</td>
+ * <td align="right">7600k</td>
+ * <td align="right">4065k</td>
+ * </tr><tr>
+ * <td align="right">900k</td>
+ * <td align="right">8500k</td>
+ * <td align="right">4565k</td>
+ * </tr>
+ * </table>
+ *
+ * <p>For decompression <tt>CBZip2InputStream</tt> allocates less
+ * memory if the bzipped input is smaller than one block.</p>
+ *
+ * <p>Instances of this class are not threadsafe.</p>
+ *
+ * <p>
+ * TODO: Update to BZip2 1.0.1
+ * </p>
+ *
+ */
+public class CBZip2OutputStream extends OutputStream implements BZip2Constants {
+
+ // Bzip2 extensions by Stefan.Liebig@compeople.de:
+ //
+ // - added a finish() method with same semantic as the java.util.GZipOutputStream#finish method
+ // i.e. flushes all compressed data to the underlying output stream
+ // - close() closes the underlying output stream
+ // but reuses now finish()
+ // - finalize() only closes the underlying output stream if not finish() has been called
+
+ /**
+ * The minimum supported blocksize <tt> == 1</tt>.
+ */
+ public static final int MIN_BLOCKSIZE = 1;
+
+ /**
+ * The maximum supported blocksize <tt> == 9</tt>.
+ */
+ public static final int MAX_BLOCKSIZE = 9;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int SETMASK = ( 1 << 21 );
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int CLEARMASK = ( ~SETMASK );
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int GREATER_ICOST = 15;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int LESSER_ICOST = 0;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int SMALL_THRESH = 20;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int DEPTH_THRESH = 10;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ */
+ protected static final int WORK_FACTOR = 30;
+
+ /**
+ * This constant is accessible by subclasses for historical purposes.
+ * If you don't know what it means then you don't need it.
+ * <p>
+ If you are ever unlucky/improbable enough
+ to get a stack overflow whilst sorting,
+ increase the following constant and try
+ again. In practice I have never seen the
+ stack go above 27 elems, so the following
+ limit seems very generous.
+ * </p>
+ */
+ protected static final int QSORT_STACK_SIZE = 1000;
+
+ /**
+ * Knuth's increments seem to work better than Incerpi-Sedgewick
+ * here. Possibly because the number of elems to sort is usually
+ * small, typically &lt;= 20.
+ */
+ private static final int[] INCS = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484 };
+
+ /**
+ * This method is accessible by subclasses for historical purposes.
+ * If you don't know what it does then you don't need it.
+ */
+ protected static void hbMakeCodeLengths( char[] len, int[] freq, int alphaSize, int maxLen ) {
+ /*
+ Nodes and heap entries run from 1. Entry 0
+ for both the heap and nodes is a sentinel.
+ */
+ final int[] heap = new int[MAX_ALPHA_SIZE * 2];
+ final int[] weight = new int[MAX_ALPHA_SIZE * 2];
+ final int[] parent = new int[MAX_ALPHA_SIZE * 2];
+
+ for ( int i = alphaSize; --i >= 0; ) {
+ weight[i + 1] = ( freq[i] == 0 ? 1 : freq[i] ) << 8;
+ }
+
+ for ( boolean tooLong = true; tooLong; ) {
+ tooLong = false;
+
+ int nNodes = alphaSize;
+ int nHeap = 0;
+ heap[0] = 0;
+ weight[0] = 0;
+ parent[0] = -2;
+
+ for ( int i = 1; i <= alphaSize; i++ ) {
+ parent[i] = -1;
+ nHeap++;
+ heap[nHeap] = i;
+
+ int zz = nHeap;
+ int tmp = heap[zz];
+ while ( weight[tmp] < weight[heap[zz >> 1]] ) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+ }
+
+ // assert (nHeap < (MAX_ALPHA_SIZE + 2)) : nHeap;
+
+ while ( nHeap > 1 ) {
+ int n1 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+
+ int yy = 0;
+ int zz = 1;
+ int tmp = heap[1];
+
+ while ( true ) {
+ yy = zz << 1;
+
+ if ( yy > nHeap ) {
+ break;
+ }
+
+ if ( ( yy < nHeap ) && ( weight[heap[yy + 1]] < weight[heap[yy]] ) ) {
+ yy++;
+ }
+
+ if ( weight[tmp] < weight[heap[yy]] ) {
+ break;
+ }
+
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+
+ heap[zz] = tmp;
+
+ int n2 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+
+ yy = 0;
+ zz = 1;
+ tmp = heap[1];
+
+ while ( true ) {
+ yy = zz << 1;
+
+ if ( yy > nHeap ) {
+ break;
+ }
+
+ if ( ( yy < nHeap ) && ( weight[heap[yy + 1]] < weight[heap[yy]] ) ) {
+ yy++;
+ }
+
+ if ( weight[tmp] < weight[heap[yy]] ) {
+ break;
+ }
+
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+
+ heap[zz] = tmp;
+ nNodes++;
+ parent[n1] = parent[n2] = nNodes;
+
+ final int weight_n1 = weight[n1];
+ final int weight_n2 = weight[n2];
+ weight[nNodes] = ( ( ( weight_n1 & 0xffffff00 ) + ( weight_n2 & 0xffffff00 ) ) | ( 1 + ( ( ( weight_n1 & 0x000000ff ) > ( weight_n2 & 0x000000ff ) ) ? ( weight_n1 & 0x000000ff )
+ : ( weight_n2 & 0x000000ff ) ) ) );
+
+ parent[nNodes] = -1;
+ nHeap++;
+ heap[nHeap] = nNodes;
+
+ tmp = 0;
+ zz = nHeap;
+ tmp = heap[zz];
+ final int weight_tmp = weight[tmp];
+ while ( weight_tmp < weight[heap[zz >> 1]] ) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+
+ }
+
+ // assert (nNodes < (MAX_ALPHA_SIZE * 2)) : nNodes;
+
+ for ( int i = 1; i <= alphaSize; i++ ) {
+ int j = 0;
+ int k = i;
+
+ for ( int parent_k; ( parent_k = parent[k] ) >= 0; ) {
+ k = parent_k;
+ j++;
+ }
+
+ len[i - 1] = (char) j;
+ if ( j > maxLen ) {
+ tooLong = true;
+ }
+ }
+
+ if ( tooLong ) {
+ for ( int i = 1; i < alphaSize; i++ ) {
+ int j = weight[i] >> 8;
+ j = 1 + ( j >> 1 );
+ weight[i] = j << 8;
+ }
+ }
+ }
+ }
+
+ private static void hbMakeCodeLengths( final byte[] len, final int[] freq, final Data dat, final int alphaSize, final int maxLen ) {
+ /*
+ Nodes and heap entries run from 1. Entry 0
+ for both the heap and nodes is a sentinel.
+ */
+ final int[] heap = dat.heap;
+ final int[] weight = dat.weight;
+ final int[] parent = dat.parent;
+
+ for ( int i = alphaSize; --i >= 0; ) {
+ weight[i + 1] = ( freq[i] == 0 ? 1 : freq[i] ) << 8;
+ }
+
+ for ( boolean tooLong = true; tooLong; ) {
+ tooLong = false;
+
+ int nNodes = alphaSize;
+ int nHeap = 0;
+ heap[0] = 0;
+ weight[0] = 0;
+ parent[0] = -2;
+
+ for ( int i = 1; i <= alphaSize; i++ ) {
+ parent[i] = -1;
+ nHeap++;
+ heap[nHeap] = i;
+
+ int zz = nHeap;
+ int tmp = heap[zz];
+ while ( weight[tmp] < weight[heap[zz >> 1]] ) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+ }
+
+ while ( nHeap > 1 ) {
+ int n1 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+
+ int yy = 0;
+ int zz = 1;
+ int tmp = heap[1];
+
+ while ( true ) {
+ yy = zz << 1;
+
+ if ( yy > nHeap ) {
+ break;
+ }
+
+ if ( ( yy < nHeap ) && ( weight[heap[yy + 1]] < weight[heap[yy]] ) ) {
+ yy++;
+ }
+
+ if ( weight[tmp] < weight[heap[yy]] ) {
+ break;
+ }
+
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+
+ heap[zz] = tmp;
+
+ int n2 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+
+ yy = 0;
+ zz = 1;
+ tmp = heap[1];
+
+ while ( true ) {
+ yy = zz << 1;
+
+ if ( yy > nHeap ) {
+ break;
+ }
+
+ if ( ( yy < nHeap ) && ( weight[heap[yy + 1]] < weight[heap[yy]] ) ) {
+ yy++;
+ }
+
+ if ( weight[tmp] < weight[heap[yy]] ) {
+ break;
+ }
+
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+
+ heap[zz] = tmp;
+ nNodes++;
+ parent[n1] = parent[n2] = nNodes;
+
+ final int weight_n1 = weight[n1];
+ final int weight_n2 = weight[n2];
+ weight[nNodes] = ( ( weight_n1 & 0xffffff00 ) + ( weight_n2 & 0xffffff00 ) )
+ | ( 1 + ( ( ( weight_n1 & 0x000000ff ) > ( weight_n2 & 0x000000ff ) ) ? ( weight_n1 & 0x000000ff ) : ( weight_n2 & 0x000000ff ) ) );
+
+ parent[nNodes] = -1;
+ nHeap++;
+ heap[nHeap] = nNodes;
+
+ tmp = 0;
+ zz = nHeap;
+ tmp = heap[zz];
+ final int weight_tmp = weight[tmp];
+ while ( weight_tmp < weight[heap[zz >> 1]] ) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+
+ }
+
+ for ( int i = 1; i <= alphaSize; i++ ) {
+ int j = 0;
+ int k = i;
+
+ for ( int parent_k; ( parent_k = parent[k] ) >= 0; ) {
+ k = parent_k;
+ j++;
+ }
+
+ len[i - 1] = (byte) j;
+ if ( j > maxLen ) {
+ tooLong = true;
+ }
+ }
+
+ if ( tooLong ) {
+ for ( int i = 1; i < alphaSize; i++ ) {
+ int j = weight[i] >> 8;
+ j = 1 + ( j >> 1 );
+ weight[i] = j << 8;
+ }
+ }
+ }
+ }
+
+ /**
+ Index of the last char in the block, so
+ the block size == last + 1.
+ */
+ private int last;
+
+ /**
+ * Index in fmap[] of original string after sorting.
+ */
+ private int origPtr;
+
+ /**
+ Always: in the range 0 .. 9.
+ The current block size is 100000 * this number.
+ */
+ private final int blockSize100k;
+
+ private boolean blockRandomised;
+
+ private int bsBuff;
+ private int bsLive;
+ private final CRC crc = new CRC();
+
+ private int nInUse;
+
+ private int nMTF;
+
+ /*
+ * Used when sorting. If too many long comparisons
+ * happen, we stop sorting, randomise the block
+ * slightly, and try again.
+ */
+ private int workDone;
+ private int workLimit;
+ private boolean firstAttempt;
+
+ private int currentChar = -1;
+ private int runLength = 0;
+
+ private int blockCRC;
+ private int combinedCRC;
+ private int allowableBlockSize;
+
+ /**
+ * All memory intensive stuff.
+ */
+ private CBZip2OutputStream.Data data;
+
+ private OutputStream out;
+
+ /**
+ * Chooses a blocksize based on the given length of the data to compress.
+ *
+ * @return
+ * The blocksize, between {@link #MIN_BLOCKSIZE} and {@link #MAX_BLOCKSIZE}
+ * both inclusive. For a negative <tt>inputLength</tt> this method returns
+ * <tt>MAX_BLOCKSIZE</tt> always.
+ *
+ * @param inputLength
+ * The length of the data which will be compressed by
+ * <tt>CBZip2OutputStream</tt>.
+ */
+ public static int chooseBlockSize( long inputLength ) {
+ return ( inputLength > 0 ) ? (int) Math.min( ( inputLength / 132000 ) + 1, 9 ) : MAX_BLOCKSIZE;
+ }
+
+ /**
+ * Constructs a new <tt>CBZip2OutputStream</tt> with a blocksize of 900k.
+ *
+ * <p><b>Attention: </b>The caller is resonsible to write the two
+ * BZip2 magic bytes <tt>"BZ"</tt> to the specified stream prior
+ * to calling this constructor.</p>
+ *
+ * @param out * the destination stream.
+ *
+ * @throws IOException
+ * if an I/O error occurs in the specified stream.
+ * @throws NullPointerException
+ * if <code>out == null</code>.
+ */
+ public CBZip2OutputStream( final OutputStream out ) throws IOException {
+ this( out, MAX_BLOCKSIZE );
+ }
+
+ /**
+ * Constructs a new <tt>CBZip2OutputStream</tt> with specified blocksize.
+ *
+ * <p><b>Attention: </b>The caller is resonsible to write the two
+ * BZip2 magic bytes <tt>"BZ"</tt> to the specified stream prior
+ * to calling this constructor.</p>
+ *
+ *
+ * @param out
+ * the destination stream.
+ * @param blockSize
+ * the blockSize as 100k units.
+ *
+ * @throws IOException
+ * if an I/O error occurs in the specified stream.
+ * @throws IllegalArgumentException
+ * if <code>(blockSize < 1) || (blockSize > 9)</code>.
+ * @throws NullPointerException
+ * if <code>out == null</code>.
+ *
+ * @see #MIN_BLOCKSIZE
+ * @see #MAX_BLOCKSIZE
+ */
+ public CBZip2OutputStream( final OutputStream out, final int blockSize ) throws IOException {
+ super();
+
+ if ( blockSize < 1 ) {
+ throw new IllegalArgumentException( "blockSize(" + blockSize + ") < 1" );
+ }
+ if ( blockSize > 9 ) {
+ throw new IllegalArgumentException( "blockSize(" + blockSize + ") > 9" );
+ }
+
+ this.blockSize100k = blockSize;
+ this.out = out;
+ init();
+ }
+
+ public void write( final int b ) throws IOException {
+ if ( this.out != null ) {
+ write0( b );
+ } else {
+ throw new IOException( "closed" );
+ }
+ }
+
+ private void writeRun() throws IOException {
+ final int lastShadow = this.last;
+
+ if ( lastShadow < this.allowableBlockSize ) {
+ final int currentCharShadow = this.currentChar;
+ final Data dataShadow = this.data;
+ dataShadow.inUse[currentCharShadow] = true;
+ final byte ch = (byte) currentCharShadow;
+
+ int runLengthShadow = this.runLength;
+ this.crc.updateCRC( currentCharShadow, runLengthShadow );
+
+ switch ( runLengthShadow ) {
+ case 1:
+ dataShadow.block[lastShadow + 2] = ch;
+ this.last = lastShadow + 1;
+ break;
+
+ case 2:
+ dataShadow.block[lastShadow + 2] = ch;
+ dataShadow.block[lastShadow + 3] = ch;
+ this.last = lastShadow + 2;
+ break;
+
+ case 3: {
+ final byte[] block = dataShadow.block;
+ block[lastShadow + 2] = ch;
+ block[lastShadow + 3] = ch;
+ block[lastShadow + 4] = ch;
+ this.last = lastShadow + 3;
+ }
+ break;
+
+ default: {
+ runLengthShadow -= 4;
+ dataShadow.inUse[runLengthShadow] = true;
+ final byte[] block = dataShadow.block;
+ block[lastShadow + 2] = ch;
+ block[lastShadow + 3] = ch;
+ block[lastShadow + 4] = ch;
+ block[lastShadow + 5] = ch;
+ block[lastShadow + 6] = (byte) runLengthShadow;
+ this.last = lastShadow + 5;
+ }
+ break;
+
+ }
+ } else {
+ endBlock();
+ initBlock();
+ writeRun();
+ }
+ }
+
+ /**
+ * Finishes compressing to the underlying stream without closing it,
+ * so that multiple compressors can write subsequently to the same
+ * output stream.
+ *
+ * @throws IOException
+ */
+ public void finish() throws IOException {
+ OutputStream outShadow = this.out;
+ if ( outShadow != null && this.data != null ) {
+ try {
+ if ( this.runLength > 0 ) {
+ writeRun();
+ }
+ this.currentChar = -1;
+ endBlock();
+ endCompression();
+ } finally {
+ this.data = null;
+ }
+ }
+ }
+
+ /**
+ * Overriden to close the stream.
+ */
+ protected void finalize() throws Throwable {
+ if ( this.data != null ) {
+ close();
+ super.finalize();
+ }
+ }
+
+ public void close() throws IOException {
+ finish();
+ OutputStream outShadow = this.out;
+ if ( outShadow != null ) {
+ try {
+ outShadow.close();
+ } finally {
+ this.out = null;
+ }
+ }
+
+ }
+
+ public void flush() throws IOException {
+ OutputStream outShadow = this.out;
+ if ( outShadow != null ) {
+ outShadow.flush();
+ }
+ }
+
+ private void init() throws IOException {
+ // write magic: done by caller who created this stream
+ //this.out.write('B');
+ //this.out.write('Z');
+
+ this.data = new Data( this.blockSize100k );
+
+ /* Write `magic' bytes h indicating file-format == huffmanised,
+ followed by a digit indicating blockSize100k.
+ */
+ bsPutUByte( 'h' );
+ bsPutUByte( '0' + this.blockSize100k );
+
+ this.combinedCRC = 0;
+ initBlock();
+ }
+
+ private void initBlock() {
+ // blockNo++;
+ this.crc.initialiseCRC();
+ this.last = -1;
+ // ch = 0;
+
+ boolean[] inUse = this.data.inUse;
+ for ( int i = 256; --i >= 0; ) {
+ inUse[i] = false;
+ }
+
+ /* 20 is just a paranoia constant */
+ this.allowableBlockSize = ( this.blockSize100k * BZip2Constants.baseBlockSize ) - 20;
+ }
+
+ private void endBlock() throws IOException {
+ this.blockCRC = this.crc.getFinalCRC();
+ this.combinedCRC = ( this.combinedCRC << 1 ) | ( this.combinedCRC >>> 31 );
+ this.combinedCRC ^= this.blockCRC;
+
+ // empty block at end of file
+ if ( this.last == -1 ) {
+ return;
+ }
+
+ /* sort the block and establish posn of original string */
+ blockSort();
+
+ /*
+ A 6-byte block header, the value chosen arbitrarily
+ as 0x314159265359 :-). A 32 bit value does not really
+ give a strong enough guarantee that the value will not
+ appear by chance in the compressed datastream. Worst-case
+ probability of this event, for a 900k block, is about
+ 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
+ For a compressed file of size 100Gb -- about 100000 blocks --
+ only a 48-bit marker will do. NB: normal compression/
+ decompression do *not* rely on these statistical properties.
+ They are only important when trying to recover blocks from
+ damaged files.
+ */
+ bsPutUByte( 0x31 );
+ bsPutUByte( 0x41 );
+ bsPutUByte( 0x59 );
+ bsPutUByte( 0x26 );
+ bsPutUByte( 0x53 );
+ bsPutUByte( 0x59 );
+
+ /* Now the block's CRC, so it is in a known place. */
+ bsPutInt( this.blockCRC );
+
+ /* Now a single bit indicating randomisation. */
+ if ( this.blockRandomised ) {
+ bsW( 1, 1 );
+ } else {
+ bsW( 1, 0 );
+ }
+
+ /* Finally, block's contents proper. */
+ moveToFrontCodeAndSend();
+ }
+
+ private void endCompression() throws IOException {
+ /*
+ Now another magic 48-bit number, 0x177245385090, to
+ indicate the end of the last block. (sqrt(pi), if
+ you want to know. I did want to use e, but it contains
+ too much repetition -- 27 18 28 18 28 46 -- for me
+ to feel statistically comfortable. Call me paranoid.)
+ */
+ bsPutUByte( 0x17 );
+ bsPutUByte( 0x72 );
+ bsPutUByte( 0x45 );
+ bsPutUByte( 0x38 );
+ bsPutUByte( 0x50 );
+ bsPutUByte( 0x90 );
+
+ bsPutInt( this.combinedCRC );
+ bsFinishedWithStream();
+ }
+
+ /**
+ * Returns the blocksize parameter specified at construction time.
+ */
+ public final int getBlockSize() {
+ return this.blockSize100k;
+ }
+
+ public void write( final byte[] buf, int offs, final int len ) throws IOException {
+ if ( offs < 0 ) {
+ throw new IndexOutOfBoundsException( "offs(" + offs + ") < 0." );
+ }
+ if ( len < 0 ) {
+ throw new IndexOutOfBoundsException( "len(" + len + ") < 0." );
+ }
+ if ( offs + len > buf.length ) {
+ throw new IndexOutOfBoundsException( "offs(" + offs + ") + len(" + len + ") > buf.length(" + buf.length + ")." );
+ }
+ if ( this.out == null ) {
+ throw new IOException( "stream closed" );
+ }
+
+ for ( int hi = offs + len; offs < hi; ) {
+ write0( buf[offs++] );
+ }
+ }
+
+ private void write0( int b ) throws IOException {
+ if ( this.currentChar != -1 ) {
+ b &= 0xff;
+ if ( this.currentChar == b ) {
+ if ( ++this.runLength > 254 ) {
+ writeRun();
+ this.currentChar = -1;
+ this.runLength = 0;
+ }
+ // else nothing to do
+ } else {
+ writeRun();
+ this.runLength = 1;
+ this.currentChar = b;
+ }
+ } else {
+ this.currentChar = b & 0xff;
+ this.runLength++;
+ }
+ }
+
+ private static void hbAssignCodes( final int[] code, final byte[] length, final int minLen, final int maxLen, final int alphaSize ) {
+ int vec = 0;
+ for ( int n = minLen; n <= maxLen; n++ ) {
+ for ( int i = 0; i < alphaSize; i++ ) {
+ if ( ( length[i] & 0xff ) == n ) {
+ code[i] = vec;
+ vec++;
+ }
+ }
+ vec <<= 1;
+ }
+ }
+
+ private void bsFinishedWithStream() throws IOException {
+ while ( this.bsLive > 0 ) {
+ int ch = this.bsBuff >> 24;
+ this.out.write( ch ); // write 8-bit
+ this.bsBuff <<= 8;
+ this.bsLive -= 8;
+ }
+ }
+
+ private void bsW( final int n, final int v ) throws IOException {
+ final OutputStream outShadow = this.out;
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+
+ this.bsBuff = bsBuffShadow | ( v << ( 32 - bsLiveShadow - n ) );
+ this.bsLive = bsLiveShadow + n;
+ }
+
+ private void bsPutUByte( final int c ) throws IOException {
+ bsW( 8, c );
+ }
+
+ private void bsPutInt( final int u ) throws IOException {
+ bsW( 8, ( u >> 24 ) & 0xff );
+ bsW( 8, ( u >> 16 ) & 0xff );
+ bsW( 8, ( u >> 8 ) & 0xff );
+ bsW( 8, u & 0xff );
+ }
+
+ private void sendMTFValues() throws IOException {
+ final byte[][] len = this.data.sendMTFValues_len;
+ final int alphaSize = this.nInUse + 2;
+
+ for ( int t = N_GROUPS; --t >= 0; ) {
+ byte[] len_t = len[t];
+ for ( int v = alphaSize; --v >= 0; ) {
+ len_t[v] = GREATER_ICOST;
+ }
+ }
+
+ /* Decide how many coding tables to use */
+ // assert (this.nMTF > 0) : this.nMTF;
+ final int nGroups = ( this.nMTF < 200 ) ? 2 : ( this.nMTF < 600 ) ? 3 : ( this.nMTF < 1200 ) ? 4 : ( this.nMTF < 2400 ) ? 5 : 6;
+
+ /* Generate an initial set of coding tables */
+ sendMTFValues0( nGroups, alphaSize );
+
+ /*
+ Iterate up to N_ITERS times to improve the tables.
+ */
+ final int nSelectors = sendMTFValues1( nGroups, alphaSize );
+
+ /* Compute MTF values for the selectors. */
+ sendMTFValues2( nGroups, nSelectors );
+
+ /* Assign actual codes for the tables. */
+ sendMTFValues3( nGroups, alphaSize );
+
+ /* Transmit the mapping table. */
+ sendMTFValues4();
+
+ /* Now the selectors. */
+ sendMTFValues5( nGroups, nSelectors );
+
+ /* Now the coding tables. */
+ sendMTFValues6( nGroups, alphaSize );
+
+ /* And finally, the block data proper */
+ sendMTFValues7( nSelectors );
+ }
+
+ private void sendMTFValues0( final int nGroups, final int alphaSize ) {
+ final byte[][] len = this.data.sendMTFValues_len;
+ final int[] mtfFreq = this.data.mtfFreq;
+
+ int remF = this.nMTF;
+ int gs = 0;
+
+ for ( int nPart = nGroups; nPart > 0; nPart-- ) {
+ final int tFreq = remF / nPart;
+ int ge = gs - 1;
+ int aFreq = 0;
+
+ for ( final int a = alphaSize - 1; ( aFreq < tFreq ) && ( ge < a ); ) {
+ aFreq += mtfFreq[++ge];
+ }
+
+ if ( ( ge > gs ) && ( nPart != nGroups ) && ( nPart != 1 ) && ( ( ( nGroups - nPart ) & 1 ) != 0 ) ) {
+ aFreq -= mtfFreq[ge--];
+ }
+
+ final byte[] len_np = len[nPart - 1];
+ for ( int v = alphaSize; --v >= 0; ) {
+ if ( ( v >= gs ) && ( v <= ge ) ) {
+ len_np[v] = LESSER_ICOST;
+ } else {
+ len_np[v] = GREATER_ICOST;
+ }
+ }
+
+ gs = ge + 1;
+ remF -= aFreq;
+ }
+ }
+
+ private int sendMTFValues1( final int nGroups, final int alphaSize ) {
+ final Data dataShadow = this.data;
+ final int[][] rfreq = dataShadow.sendMTFValues_rfreq;
+ final int[] fave = dataShadow.sendMTFValues_fave;
+ final short[] cost = dataShadow.sendMTFValues_cost;
+ final char[] sfmap = dataShadow.sfmap;
+ final byte[] selector = dataShadow.selector;
+ final byte[][] len = dataShadow.sendMTFValues_len;
+ final byte[] len_0 = len[0];
+ final byte[] len_1 = len[1];
+ final byte[] len_2 = len[2];
+ final byte[] len_3 = len[3];
+ final byte[] len_4 = len[4];
+ final byte[] len_5 = len[5];
+ final int nMTFShadow = this.nMTF;
+
+ int nSelectors = 0;
+
+ for ( int iter = 0; iter < N_ITERS; iter++ ) {
+ for ( int t = nGroups; --t >= 0; ) {
+ fave[t] = 0;
+ int[] rfreqt = rfreq[t];
+ for ( int i = alphaSize; --i >= 0; ) {
+ rfreqt[i] = 0;
+ }
+ }
+
+ nSelectors = 0;
+
+ for ( int gs = 0; gs < this.nMTF; ) {
+ /* Set group start & end marks. */
+
+ /*
+ Calculate the cost of this group as coded
+ by each of the coding tables.
+ */
+
+ final int ge = Math.min( gs + G_SIZE - 1, nMTFShadow - 1 );
+
+ if ( nGroups == N_GROUPS ) {
+ // unrolled version of the else-block
+
+ short cost0 = 0;
+ short cost1 = 0;
+ short cost2 = 0;
+ short cost3 = 0;
+ short cost4 = 0;
+ short cost5 = 0;
+
+ for ( int i = gs; i <= ge; i++ ) {
+ final int icv = sfmap[i];
+ cost0 += len_0[icv] & 0xff;
+ cost1 += len_1[icv] & 0xff;
+ cost2 += len_2[icv] & 0xff;
+ cost3 += len_3[icv] & 0xff;
+ cost4 += len_4[icv] & 0xff;
+ cost5 += len_5[icv] & 0xff;
+ }
+
+ cost[0] = cost0;
+ cost[1] = cost1;
+ cost[2] = cost2;
+ cost[3] = cost3;
+ cost[4] = cost4;
+ cost[5] = cost5;
+
+ } else {
+ for ( int t = nGroups; --t >= 0; ) {
+ cost[t] = 0;
+ }
+
+ for ( int i = gs; i <= ge; i++ ) {
+ final int icv = sfmap[i];
+ for ( int t = nGroups; --t >= 0; ) {
+ cost[t] += len[t][icv] & 0xff;
+ }
+ }
+ }
+
+ /*
+ Find the coding table which is best for this group,
+ and record its identity in the selector table.
+ */
+ int bt = -1;
+ for ( int t = nGroups, bc = 999999999; --t >= 0; ) {
+ final int cost_t = cost[t];
+ if ( cost_t < bc ) {
+ bc = cost_t;
+ bt = t;
+ }
+ }
+
+ fave[bt]++;
+ selector[nSelectors] = (byte) bt;
+ nSelectors++;
+
+ /*
+ Increment the symbol frequencies for the selected table.
+ */
+ final int[] rfreq_bt = rfreq[bt];
+ for ( int i = gs; i <= ge; i++ ) {
+ rfreq_bt[sfmap[i]]++;
+ }
+
+ gs = ge + 1;
+ }
+
+ /*
+ Recompute the tables based on the accumulated frequencies.
+ */
+ for ( int t = 0; t < nGroups; t++ ) {
+ hbMakeCodeLengths( len[t], rfreq[t], this.data, alphaSize, 20 );
+ }
+ }
+
+ return nSelectors;
+ }
+
+ private void sendMTFValues2( final int nGroups, final int nSelectors ) {
+ // assert (nGroups < 8) : nGroups;
+
+ final Data dataShadow = this.data;
+ byte[] pos = dataShadow.sendMTFValues2_pos;
+
+ for ( int i = nGroups; --i >= 0; ) {
+ pos[i] = (byte) i;
+ }
+
+ for ( int i = 0; i < nSelectors; i++ ) {
+ final byte ll_i = dataShadow.selector[i];
+ byte tmp = pos[0];
+ int j = 0;
+
+ while ( ll_i != tmp ) {
+ j++;
+ byte tmp2 = tmp;
+ tmp = pos[j];
+ pos[j] = tmp2;
+ }
+
+ pos[0] = tmp;
+ dataShadow.selectorMtf[i] = (byte) j;
+ }
+ }
+
+ private void sendMTFValues3( final int nGroups, final int alphaSize ) {
+ int[][] code = this.data.sendMTFValues_code;
+ byte[][] len = this.data.sendMTFValues_len;
+
+ for ( int t = 0; t < nGroups; t++ ) {
+ int minLen = 32;
+ int maxLen = 0;
+ final byte[] len_t = len[t];
+ for ( int i = alphaSize; --i >= 0; ) {
+ final int l = len_t[i] & 0xff;
+ if ( l > maxLen ) {
+ maxLen = l;
+ }
+ if ( l < minLen ) {
+ minLen = l;
+ }
+ }
+
+ // assert (maxLen <= 20) : maxLen;
+ // assert (minLen >= 1) : minLen;
+
+ hbAssignCodes( code[t], len[t], minLen, maxLen, alphaSize );
+ }
+ }
+
+ private void sendMTFValues4() throws IOException {
+ final boolean[] inUse = this.data.inUse;
+ final boolean[] inUse16 = this.data.sentMTFValues4_inUse16;
+
+ for ( int i = 16; --i >= 0; ) {
+ inUse16[i] = false;
+ final int i16 = i * 16;
+ for ( int j = 16; --j >= 0; ) {
+ if ( inUse[i16 + j] ) {
+ inUse16[i] = true;
+ }
+ }
+ }
+
+ for ( int i = 0; i < 16; i++ ) {
+ bsW( 1, inUse16[i] ? 1 : 0 );
+ }
+
+ final OutputStream outShadow = this.out;
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ for ( int i = 0; i < 16; i++ ) {
+ if ( inUse16[i] ) {
+ final int i16 = i * 16;
+ for ( int j = 0; j < 16; j++ ) {
+ // inlined: bsW(1, inUse[i16 + j] ? 1 : 0);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ if ( inUse[i16 + j] ) {
+ bsBuffShadow |= 1 << ( 32 - bsLiveShadow - 1 );
+ }
+ bsLiveShadow++;
+ }
+ }
+ }
+
+ this.bsBuff = bsBuffShadow;
+ this.bsLive = bsLiveShadow;
+ }
+
+ private void sendMTFValues5( final int nGroups, final int nSelectors ) throws IOException {
+ bsW( 3, nGroups );
+ bsW( 15, nSelectors );
+
+ final OutputStream outShadow = this.out;
+ final byte[] selectorMtf = this.data.selectorMtf;
+
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ for ( int i = 0; i < nSelectors; i++ ) {
+ for ( int j = 0, hj = selectorMtf[i] & 0xff; j < hj; j++ ) {
+ // inlined: bsW(1, 1);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 );
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ bsBuffShadow |= 1 << ( 32 - bsLiveShadow - 1 );
+ bsLiveShadow++;
+ }
+
+ // inlined: bsW(1, 0);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 );
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ //bsBuffShadow |= 0 << (32 - bsLiveShadow - 1);
+ bsLiveShadow++;
+ }
+
+ this.bsBuff = bsBuffShadow;
+ this.bsLive = bsLiveShadow;
+ }
+
+ private void sendMTFValues6( final int nGroups, final int alphaSize ) throws IOException {
+ final byte[][] len = this.data.sendMTFValues_len;
+ final OutputStream outShadow = this.out;
+
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ for ( int t = 0; t < nGroups; t++ ) {
+ byte[] len_t = len[t];
+ int curr = len_t[0] & 0xff;
+
+ // inlined: bsW(5, curr);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ bsBuffShadow |= curr << ( 32 - bsLiveShadow - 5 );
+ bsLiveShadow += 5;
+
+ for ( int i = 0; i < alphaSize; i++ ) {
+ int lti = len_t[i] & 0xff;
+ while ( curr < lti ) {
+ // inlined: bsW(2, 2);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ bsBuffShadow |= 2 << ( 32 - bsLiveShadow - 2 );
+ bsLiveShadow += 2;
+
+ curr++; /* 10 */
+ }
+
+ while ( curr > lti ) {
+ // inlined: bsW(2, 3);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ bsBuffShadow |= 3 << ( 32 - bsLiveShadow - 2 );
+ bsLiveShadow += 2;
+
+ curr--; /* 11 */
+ }
+
+ // inlined: bsW(1, 0);
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 ); // write 8-bit
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ // bsBuffShadow |= 0 << (32 - bsLiveShadow - 1);
+ bsLiveShadow++;
+ }
+ }
+
+ this.bsBuff = bsBuffShadow;
+ this.bsLive = bsLiveShadow;
+ }
+
+ private void sendMTFValues7( final int nSelectors ) throws IOException {
+ final Data dataShadow = this.data;
+ final byte[][] len = dataShadow.sendMTFValues_len;
+ final int[][] code = dataShadow.sendMTFValues_code;
+ final OutputStream outShadow = this.out;
+ final byte[] selector = dataShadow.selector;
+ final char[] sfmap = dataShadow.sfmap;
+ final int nMTFShadow = this.nMTF;
+
+ int selCtr = 0;
+
+ int bsLiveShadow = this.bsLive;
+ int bsBuffShadow = this.bsBuff;
+
+ for ( int gs = 0; gs < nMTFShadow; ) {
+ final int ge = Math.min( gs + G_SIZE - 1, nMTFShadow - 1 );
+ final int selector_selCtr = selector[selCtr] & 0xff;
+ final int[] code_selCtr = code[selector_selCtr];
+ final byte[] len_selCtr = len[selector_selCtr];
+
+ while ( gs <= ge ) {
+ final int sfmap_i = sfmap[gs];
+
+ //
+ // inlined: bsW(len_selCtr[sfmap_i] & 0xff,
+ // code_selCtr[sfmap_i]);
+ //
+ while ( bsLiveShadow >= 8 ) {
+ outShadow.write( bsBuffShadow >> 24 );
+ bsBuffShadow <<= 8;
+ bsLiveShadow -= 8;
+ }
+ final int n = len_selCtr[sfmap_i] & 0xFF;
+ bsBuffShadow |= code_selCtr[sfmap_i] << ( 32 - bsLiveShadow - n );
+ bsLiveShadow += n;
+
+ gs++;
+ }
+
+ gs = ge + 1;
+ selCtr++;
+ }
+
+ this.bsBuff = bsBuffShadow;
+ this.bsLive = bsLiveShadow;
+ }
+
+ private void moveToFrontCodeAndSend() throws IOException {
+ bsW( 24, this.origPtr );
+ generateMTFValues();
+ sendMTFValues();
+ }
+
+ /**
+ * This is the most hammered method of this class.
+ *
+ * <p>This is the version using unrolled loops. Normally I never
+ * use such ones in Java code. The unrolling has shown a
+ * noticable performance improvement on JRE 1.4.2 (Linux i586 /
+ * HotSpot Client). Of course it depends on the JIT compiler of
+ * the vm.</p>
+ */
+ private boolean mainSimpleSort( final Data dataShadow, final int lo, final int hi, final int d ) {
+ final int bigN = hi - lo + 1;
+ if ( bigN < 2 ) {
+ return this.firstAttempt && ( this.workDone > this.workLimit );
+ }
+
+ int hp = 0;
+ while ( INCS[hp] < bigN ) {
+ hp++;
+ }
+
+ final int[] fmap = dataShadow.fmap;
+ final char[] quadrant = dataShadow.quadrant;
+ final byte[] block = dataShadow.block;
+ final int lastShadow = this.last;
+ final int lastPlus1 = lastShadow + 1;
+ final boolean firstAttemptShadow = this.firstAttempt;
+ final int workLimitShadow = this.workLimit;
+ int workDoneShadow = this.workDone;
+
+ // Following block contains unrolled code which could be shortened by
+ // coding it in additional loops.
+
+ HP: while ( --hp >= 0 ) {
+ final int h = INCS[hp];
+ final int mj = lo + h - 1;
+
+ for ( int i = lo + h; i <= hi; ) {
+ // copy
+ for ( int k = 3; ( i <= hi ) && ( --k >= 0 ); i++ ) {
+ final int v = fmap[i];
+ final int vd = v + d;
+ int j = i;
+
+ // for (int a;
+ // (j > mj) && mainGtU((a = fmap[j - h]) + d, vd,
+ // block, quadrant, lastShadow);
+ // j -= h) {
+ // fmap[j] = a;
+ // }
+ //
+ // unrolled version:
+
+ // start inline mainGTU
+ boolean onceRunned = false;
+ int a = 0;
+
+ HAMMER: while ( true ) {
+ if ( onceRunned ) {
+ fmap[j] = a;
+ if ( ( j -= h ) <= mj ) {
+ break HAMMER;
+ }
+ } else {
+ onceRunned = true;
+ }
+
+ a = fmap[j - h];
+ int i1 = a + d;
+ int i2 = vd;
+
+ // following could be done in a loop, but
+ // unrolled it for performance:
+ if ( block[i1 + 1] == block[i2 + 1] ) {
+ if ( block[i1 + 2] == block[i2 + 2] ) {
+ if ( block[i1 + 3] == block[i2 + 3] ) {
+ if ( block[i1 + 4] == block[i2 + 4] ) {
+ if ( block[i1 + 5] == block[i2 + 5] ) {
+ if ( block[( i1 += 6 )] == block[( i2 += 6 )] ) {
+ int x = lastShadow;
+ X: while ( x > 0 ) {
+ x -= 4;
+
+ if ( block[i1 + 1] == block[i2 + 1] ) {
+ if ( quadrant[i1] == quadrant[i2] ) {
+ if ( block[i1 + 2] == block[i2 + 2] ) {
+ if ( quadrant[i1 + 1] == quadrant[i2 + 1] ) {
+ if ( block[i1 + 3] == block[i2 + 3] ) {
+ if ( quadrant[i1 + 2] == quadrant[i2 + 2] ) {
+ if ( block[i1 + 4] == block[i2 + 4] ) {
+ if ( quadrant[i1 + 3] == quadrant[i2 + 3] ) {
+ if ( ( i1 += 4 ) >= lastPlus1 ) {
+ i1 -= lastPlus1;
+ }
+ if ( ( i2 += 4 ) >= lastPlus1 ) {
+ i2 -= lastPlus1;
+ }
+ workDoneShadow++;
+ continue X;
+ } else if ( ( quadrant[i1 + 3] > quadrant[i2 + 3] ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 4] & 0xff ) > ( block[i2 + 4] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( quadrant[i1 + 2] > quadrant[i2 + 2] ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 3] & 0xff ) > ( block[i2 + 3] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( quadrant[i1 + 1] > quadrant[i2 + 1] ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 2] & 0xff ) > ( block[i2 + 2] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( quadrant[i1] > quadrant[i2] ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 1] & 0xff ) > ( block[i2 + 1] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+
+ }
+ break HAMMER;
+ } // while x > 0
+ else {
+ if ( ( block[i1] & 0xff ) > ( block[i2] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ }
+ } else if ( ( block[i1 + 5] & 0xff ) > ( block[i2 + 5] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 4] & 0xff ) > ( block[i2 + 4] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 3] & 0xff ) > ( block[i2 + 3] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 2] & 0xff ) > ( block[i2 + 2] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+ } else if ( ( block[i1 + 1] & 0xff ) > ( block[i2 + 1] & 0xff ) ) {
+ continue HAMMER;
+ } else {
+ break HAMMER;
+ }
+
+ } // HAMMER
+ // end inline mainGTU
+
+ fmap[j] = v;
+ }
+
+ if ( firstAttemptShadow && ( i <= hi ) && ( workDoneShadow > workLimitShadow ) ) {
+ break HP;
+ }
+ }
+ }
+
+ this.workDone = workDoneShadow;
+ return firstAttemptShadow && ( workDoneShadow > workLimitShadow );
+ }
+
+ private static void vswap( int[] fmap, int p1, int p2, int n ) {
+ n += p1;
+ while ( p1 < n ) {
+ int t = fmap[p1];
+ fmap[p1++] = fmap[p2];
+ fmap[p2++] = t;
+ }
+ }
+
+ private static byte med3( byte a, byte b, byte c ) {
+ return ( a < b ) ? ( b < c ? b : a < c ? c : a ) : ( b > c ? b : a > c ? c : a );
+ }
+
+ private void blockSort() {
+ this.workLimit = WORK_FACTOR * this.last;
+ this.workDone = 0;
+ this.blockRandomised = false;
+ this.firstAttempt = true;
+ mainSort();
+
+ if ( this.firstAttempt && ( this.workDone > this.workLimit ) ) {
+ randomiseBlock();
+ this.workLimit = this.workDone = 0;
+ this.firstAttempt = false;
+ mainSort();
+ }
+
+ int[] fmap = this.data.fmap;
+ this.origPtr = -1;
+ for ( int i = 0, lastShadow = this.last; i <= lastShadow; i++ ) {
+ if ( fmap[i] == 0 ) {
+ this.origPtr = i;
+ break;
+ }
+ }
+
+ // assert (this.origPtr != -1) : this.origPtr;
+ }
+
+ /**
+ * Method "mainQSort3", file "blocksort.c", BZip2 1.0.2
+ */
+ private void mainQSort3( final Data dataShadow, final int loSt, final int hiSt, final int dSt ) {
+ final int[] stack_ll = dataShadow.stack_ll;
+ final int[] stack_hh = dataShadow.stack_hh;
+ final int[] stack_dd = dataShadow.stack_dd;
+ final int[] fmap = dataShadow.fmap;
+ final byte[] block = dataShadow.block;
+
+ stack_ll[0] = loSt;
+ stack_hh[0] = hiSt;
+ stack_dd[0] = dSt;
+
+ for ( int sp = 1; --sp >= 0; ) {
+ final int lo = stack_ll[sp];
+ final int hi = stack_hh[sp];
+ final int d = stack_dd[sp];
+
+ if ( ( hi - lo < SMALL_THRESH ) || ( d > DEPTH_THRESH ) ) {
+ if ( mainSimpleSort( dataShadow, lo, hi, d ) ) {
+ return;
+ }
+ } else {
+ final int d1 = d + 1;
+ final int med = med3( block[fmap[lo] + d1], block[fmap[hi] + d1], block[fmap[( lo + hi ) >> 1] + d1] ) & 0xff;
+
+ int unLo = lo;
+ int unHi = hi;
+ int ltLo = lo;
+ int gtHi = hi;
+
+ while ( true ) {
+ while ( unLo <= unHi ) {
+ final int n = ( block[fmap[unLo] + d1] & 0xff ) - med;
+ if ( n == 0 ) {
+ final int temp = fmap[unLo];
+ fmap[unLo++] = fmap[ltLo];
+ fmap[ltLo++] = temp;
+ } else if ( n < 0 ) {
+ unLo++;
+ } else {
+ break;
+ }
+ }
+
+ while ( unLo <= unHi ) {
+ final int n = ( block[fmap[unHi] + d1] & 0xff ) - med;
+ if ( n == 0 ) {
+ final int temp = fmap[unHi];
+ fmap[unHi--] = fmap[gtHi];
+ fmap[gtHi--] = temp;
+ } else if ( n > 0 ) {
+ unHi--;
+ } else {
+ break;
+ }
+ }
+
+ if ( unLo <= unHi ) {
+ final int temp = fmap[unLo];
+ fmap[unLo++] = fmap[unHi];
+ fmap[unHi--] = temp;
+ } else {
+ break;
+ }
+ }
+
+ if ( gtHi < ltLo ) {
+ stack_ll[sp] = lo;
+ stack_hh[sp] = hi;
+ stack_dd[sp] = d1;
+ sp++;
+ } else {
+ int n = ( ( ltLo - lo ) < ( unLo - ltLo ) ) ? ( ltLo - lo ) : ( unLo - ltLo );
+ vswap( fmap, lo, unLo - n, n );
+ int m = ( ( hi - gtHi ) < ( gtHi - unHi ) ) ? ( hi - gtHi ) : ( gtHi - unHi );
+ vswap( fmap, unLo, hi - m + 1, m );
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - ( gtHi - unHi ) + 1;
+
+ stack_ll[sp] = lo;
+ stack_hh[sp] = n;
+ stack_dd[sp] = d;
+ sp++;
+
+ stack_ll[sp] = n + 1;
+ stack_hh[sp] = m - 1;
+ stack_dd[sp] = d1;
+ sp++;
+
+ stack_ll[sp] = m;
+ stack_hh[sp] = hi;
+ stack_dd[sp] = d;
+ sp++;
+ }
+ }
+ }
+ }
+
+ private void mainSort() {
+ final Data dataShadow = this.data;
+ final int[] runningOrder = dataShadow.mainSort_runningOrder;
+ final int[] copy = dataShadow.mainSort_copy;
+ final boolean[] bigDone = dataShadow.mainSort_bigDone;
+ final int[] ftab = dataShadow.ftab;
+ final byte[] block = dataShadow.block;
+ final int[] fmap = dataShadow.fmap;
+ final char[] quadrant = dataShadow.quadrant;
+ final int lastShadow = this.last;
+ final int workLimitShadow = this.workLimit;
+ final boolean firstAttemptShadow = this.firstAttempt;
+
+ // Set up the 2-byte frequency table
+ for ( int i = 65537; --i >= 0; ) {
+ ftab[i] = 0;
+ }
+
+ /*
+ In the various block-sized structures, live data runs
+ from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First,
+ set up the overshoot area for block.
+ */
+ for ( int i = 0; i < NUM_OVERSHOOT_BYTES; i++ ) {
+ block[lastShadow + i + 2] = block[( i % ( lastShadow + 1 ) ) + 1];
+ }
+ for ( int i = lastShadow + NUM_OVERSHOOT_BYTES; --i >= 0; ) {
+ quadrant[i] = 0;
+ }
+ block[0] = block[lastShadow + 1];
+
+ // Complete the initial radix sort:
+
+ int c1 = block[0] & 0xff;
+ for ( int i = 0; i <= lastShadow; i++ ) {
+ final int c2 = block[i + 1] & 0xff;
+ ftab[( c1 << 8 ) + c2]++;
+ c1 = c2;
+ }
+
+ for ( int i = 1; i <= 65536; i++ )
+ ftab[i] += ftab[i - 1];
+
+ c1 = block[1] & 0xff;
+ for ( int i = 0; i < lastShadow; i++ ) {
+ final int c2 = block[i + 2] & 0xff;
+ fmap[--ftab[( c1 << 8 ) + c2]] = i;
+ c1 = c2;
+ }
+
+ fmap[--ftab[( ( block[lastShadow + 1] & 0xff ) << 8 ) + ( block[1] & 0xff )]] = lastShadow;
+
+ /*
+ Now ftab contains the first loc of every small bucket.
+ Calculate the running order, from smallest to largest
+ big bucket.
+ */
+ for ( int i = 256; --i >= 0; ) {
+ bigDone[i] = false;
+ runningOrder[i] = i;
+ }
+
+ for ( int h = 364; h != 1; ) {
+ h /= 3;
+ for ( int i = h; i <= 255; i++ ) {
+ final int vv = runningOrder[i];
+ final int a = ftab[( vv + 1 ) << 8] - ftab[vv << 8];
+ final int b = h - 1;
+ int j = i;
+ for ( int ro = runningOrder[j - h]; ( ftab[( ro + 1 ) << 8] - ftab[ro << 8] ) > a; ro = runningOrder[j - h] ) {
+ runningOrder[j] = ro;
+ j -= h;
+ if ( j <= b ) {
+ break;
+ }
+ }
+ runningOrder[j] = vv;
+ }
+ }
+
+ /*
+ The main sorting loop.
+ */
+ for ( int i = 0; i <= 255; i++ ) {
+ /*
+ Process big buckets, starting with the least full.
+ */
+ final int ss = runningOrder[i];
+
+ // Step 1:
+ /*
+ Complete the big bucket [ss] by quicksorting
+ any unsorted small buckets [ss, j]. Hopefully
+ previous pointer-scanning phases have already
+ completed many of the small buckets [ss, j], so
+ we don't have to sort them at all.
+ */
+ for ( int j = 0; j <= 255; j++ ) {
+ final int sb = ( ss << 8 ) + j;
+ final int ftab_sb = ftab[sb];
+ if ( ( ftab_sb & SETMASK ) != SETMASK ) {
+ final int lo = ftab_sb & CLEARMASK;
+ final int hi = ( ftab[sb + 1] & CLEARMASK ) - 1;
+ if ( hi > lo ) {
+ mainQSort3( dataShadow, lo, hi, 2 );
+ if ( firstAttemptShadow && ( this.workDone > workLimitShadow ) ) {
+ return;
+ }
+ }
+ ftab[sb] = ftab_sb | SETMASK;
+ }
+ }
+
+ // Step 2:
+ // Now scan this big bucket so as to synthesise the
+ // sorted order for small buckets [t, ss] for all t != ss.
+
+ for ( int j = 0; j <= 255; j++ ) {
+ copy[j] = ftab[( j << 8 ) + ss] & CLEARMASK;
+ }
+
+ for ( int j = ftab[ss << 8] & CLEARMASK, hj = ( ftab[( ss + 1 ) << 8] & CLEARMASK ); j < hj; j++ ) {
+ final int fmap_j = fmap[j];
+ c1 = block[fmap_j] & 0xff;
+ if ( !bigDone[c1] ) {
+ fmap[copy[c1]] = ( fmap_j == 0 ) ? lastShadow : ( fmap_j - 1 );
+ copy[c1]++;
+ }
+ }
+
+ for ( int j = 256; --j >= 0; )
+ ftab[( j << 8 ) + ss] |= SETMASK;
+
+ // Step 3:
+ /*
+ The ss big bucket is now done. Record this fact,
+ and update the quadrant descriptors. Remember to
+ update quadrants in the overshoot area too, if
+ necessary. The "if (i < 255)" test merely skips
+ this updating for the last bucket processed, since
+ updating for the last bucket is pointless.
+ */
+ bigDone[ss] = true;
+
+ if ( i < 255 ) {
+ final int bbStart = ftab[ss << 8] & CLEARMASK;
+ final int bbSize = ( ftab[( ss + 1 ) << 8] & CLEARMASK ) - bbStart;
+ int shifts = 0;
+
+ while ( ( bbSize >> shifts ) > 65534 ) {
+ shifts++;
+ }
+
+ for ( int j = 0; j < bbSize; j++ ) {
+ final int a2update = fmap[bbStart + j];
+ final char qVal = (char) ( j >> shifts );
+ quadrant[a2update] = qVal;
+ if ( a2update < NUM_OVERSHOOT_BYTES ) {
+ quadrant[a2update + lastShadow + 1] = qVal;
+ }
+ }
+ }
+
+ }
+ }
+
+ private void randomiseBlock() {
+ final boolean[] inUse = this.data.inUse;
+ final byte[] block = this.data.block;
+ final int lastShadow = this.last;
+
+ for ( int i = 256; --i >= 0; )
+ inUse[i] = false;
+
+ int rNToGo = 0;
+ int rTPos = 0;
+ for ( int i = 0, j = 1; i <= lastShadow; i = j, j++ ) {
+ if ( rNToGo == 0 ) {
+ rNToGo = (char) BZip2Constants.rNums[rTPos];
+ if ( ++rTPos == 512 ) {
+ rTPos = 0;
+ }
+ }
+
+ rNToGo--;
+ block[j] ^= ( ( rNToGo == 1 ) ? 1 : 0 );
+
+ // handle 16 bit signed numbers
+ inUse[block[j] & 0xff] = true;
+ }
+
+ this.blockRandomised = true;
+ }
+
+ private void generateMTFValues() {
+ final int lastShadow = this.last;
+ final Data dataShadow = this.data;
+ final boolean[] inUse = dataShadow.inUse;
+ final byte[] block = dataShadow.block;
+ final int[] fmap = dataShadow.fmap;
+ final char[] sfmap = dataShadow.sfmap;
+ final int[] mtfFreq = dataShadow.mtfFreq;
+ final byte[] unseqToSeq = dataShadow.unseqToSeq;
+ final byte[] yy = dataShadow.generateMTFValues_yy;
+
+ // make maps
+ int nInUseShadow = 0;
+ for ( int i = 0; i < 256; i++ ) {
+ if ( inUse[i] ) {
+ unseqToSeq[i] = (byte) nInUseShadow;
+ nInUseShadow++;
+ }
+ }
+ this.nInUse = nInUseShadow;
+
+ final int eob = nInUseShadow + 1;
+
+ for ( int i = eob; i >= 0; i-- ) {
+ mtfFreq[i] = 0;
+ }
+
+ for ( int i = nInUseShadow; --i >= 0; ) {
+ yy[i] = (byte) i;
+ }
+
+ int wr = 0;
+ int zPend = 0;
+
+ for ( int i = 0; i <= lastShadow; i++ ) {
+ final byte ll_i = unseqToSeq[block[fmap[i]] & 0xff];
+ byte tmp = yy[0];
+ int j = 0;
+
+ while ( ll_i != tmp ) {
+ j++;
+ byte tmp2 = tmp;
+ tmp = yy[j];
+ yy[j] = tmp2;
+ }
+ yy[0] = tmp;
+
+ if ( j == 0 ) {
+ zPend++;
+ } else {
+ if ( zPend > 0 ) {
+ zPend--;
+ while ( true ) {
+ if ( ( zPend & 1 ) == 0 ) {
+ sfmap[wr] = RUNA;
+ wr++;
+ mtfFreq[RUNA]++;
+ } else {
+ sfmap[wr] = RUNB;
+ wr++;
+ mtfFreq[RUNB]++;
+ }
+
+ if ( zPend >= 2 ) {
+ zPend = ( zPend - 2 ) >> 1;
+ } else {
+ break;
+ }
+ }
+ zPend = 0;
+ }
+ sfmap[wr] = (char) ( j + 1 );
+ wr++;
+ mtfFreq[j + 1]++;
+ }
+ }
+
+ if ( zPend > 0 ) {
+ zPend--;
+ while ( true ) {
+ if ( ( zPend & 1 ) == 0 ) {
+ sfmap[wr] = RUNA;
+ wr++;
+ mtfFreq[RUNA]++;
+ } else {
+ sfmap[wr] = RUNB;
+ wr++;
+ mtfFreq[RUNB]++;
+ }
+
+ if ( zPend >= 2 ) {
+ zPend = ( zPend - 2 ) >> 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ sfmap[wr] = (char) eob;
+ mtfFreq[eob]++;
+ this.nMTF = wr + 1;
+ }
+
+ private static final class Data extends Object {
+
+ // with blockSize 900k
+ final boolean[] inUse = new boolean[256]; // 256 byte
+ final byte[] unseqToSeq = new byte[256]; // 256 byte
+ final int[] mtfFreq = new int[MAX_ALPHA_SIZE]; // 1032 byte
+ final byte[] selector = new byte[MAX_SELECTORS]; // 18002 byte
+ final byte[] selectorMtf = new byte[MAX_SELECTORS]; // 18002 byte
+
+ final byte[] generateMTFValues_yy = new byte[256]; // 256 byte
+ final byte[][] sendMTFValues_len = new byte[N_GROUPS][MAX_ALPHA_SIZE]; // 1548 byte
+ final int[][] sendMTFValues_rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192 byte
+ final int[] sendMTFValues_fave = new int[N_GROUPS]; // 24 byte
+ final short[] sendMTFValues_cost = new short[N_GROUPS]; // 12 byte
+ final int[][] sendMTFValues_code = new int[N_GROUPS][MAX_ALPHA_SIZE]; // 6192 byte
+ final byte[] sendMTFValues2_pos = new byte[N_GROUPS]; // 6 byte
+ final boolean[] sentMTFValues4_inUse16 = new boolean[16]; // 16 byte
+
+ final int[] stack_ll = new int[QSORT_STACK_SIZE]; // 4000 byte
+ final int[] stack_hh = new int[QSORT_STACK_SIZE]; // 4000 byte
+ final int[] stack_dd = new int[QSORT_STACK_SIZE]; // 4000 byte
+
+ final int[] mainSort_runningOrder = new int[256]; // 1024 byte
+ final int[] mainSort_copy = new int[256]; // 1024 byte
+ final boolean[] mainSort_bigDone = new boolean[256]; // 256 byte
+
+ final int[] heap = new int[MAX_ALPHA_SIZE + 2]; // 1040 byte
+ final int[] weight = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte
+ final int[] parent = new int[MAX_ALPHA_SIZE * 2]; // 2064 byte
+
+ final int[] ftab = new int[65537]; // 262148 byte
+ // ------------
+ // 333408 byte
+
+ final byte[] block; // 900021 byte
+ final int[] fmap; // 3600000 byte
+ final char[] sfmap; // 3600000 byte
+ // ------------
+ // 8433529 byte
+ // ============
+
+ /**
+ * Array instance identical to sfmap, both are used only temporarily and indepently,
+ * so we do not need to allocate additional memory.
+ */
+ final char[] quadrant;
+
+ Data( int blockSize100k ) {
+ super();
+
+ final int n = blockSize100k * BZip2Constants.baseBlockSize;
+ this.block = new byte[( n + 1 + NUM_OVERSHOOT_BYTES )];
+ this.fmap = new int[n];
+ this.sfmap = new char[2 * n];
+ this.quadrant = this.sfmap;
+ }
+
+ }
+
+}
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CRC.java b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CRC.java
new file mode 100644
index 000000000..5184af044
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/CRC.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.apache.tools.bzip2;
+
+/**
+ * A simple class the hold and calculate the CRC for sanity checking
+ * of the data.
+ *
+ */
+final class CRC {
+ static final int crc32Table[] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f,
+ 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b,
+ 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57,
+ 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+ 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f,
+ 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c,
+ 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0,
+ 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4,
+ 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+ 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c,
+ 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59,
+ 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d,
+ 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91,
+ 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+ 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9,
+ 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad,
+ 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096,
+ 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082,
+ 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+ 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa,
+ 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06,
+ 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 };
+
+ CRC() {
+ initialiseCRC();
+ }
+
+ void initialiseCRC() {
+ globalCrc = 0xffffffff;
+ }
+
+ int getFinalCRC() {
+ return ~globalCrc;
+ }
+
+ int getGlobalCRC() {
+ return globalCrc;
+ }
+
+ void setGlobalCRC( int newCrc ) {
+ globalCrc = newCrc;
+ }
+
+ void updateCRC( int inCh ) {
+ int temp = ( globalCrc >> 24 ) ^ inCh;
+ if ( temp < 0 ) {
+ temp = 256 + temp;
+ }
+ globalCrc = ( globalCrc << 8 ) ^ CRC.crc32Table[temp];
+ }
+
+ void updateCRC( int inCh, int repeat ) {
+ int globalCrcShadow = this.globalCrc;
+ while ( repeat-- > 0 ) {
+ int temp = ( globalCrcShadow >> 24 ) ^ inCh;
+ globalCrcShadow = ( globalCrcShadow << 8 ) ^ crc32Table[( temp >= 0 ) ? temp : ( temp + 256 )];
+ }
+ this.globalCrc = globalCrcShadow;
+ }
+
+ int globalCrc;
+}
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/LICENSE b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/LICENSE
new file mode 100644
index 000000000..f820d4bd3
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/LICENSE
@@ -0,0 +1,203 @@
+/*
+ * Apache License
+ * Version 2.0, January 2004
+ * http://www.apache.org/licenses/
+ *
+ * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ * 1. Definitions.
+ *
+ * "License" shall mean the terms and conditions for use, reproduction,
+ * and distribution as defined by Sections 1 through 9 of this document.
+ *
+ * "Licensor" shall mean the copyright owner or entity authorized by
+ * the copyright owner that is granting the License.
+ *
+ * "Legal Entity" shall mean the union of the acting entity and all
+ * other entities that control, are controlled by, or are under common
+ * control with that entity. For the purposes of this definition,
+ * "control" means (i) the power, direct or indirect, to cause the
+ * direction or management of such entity, whether by contract or
+ * otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ * outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ * "You" (or "Your") shall mean an individual or Legal Entity
+ * exercising permissions granted by this License.
+ *
+ * "Source" form shall mean the preferred form for making modifications,
+ * including but not limited to software source code, documentation
+ * source, and configuration files.
+ *
+ * "Object" form shall mean any form resulting from mechanical
+ * transformation or translation of a Source form, including but
+ * not limited to compiled object code, generated documentation,
+ * and conversions to other media types.
+ *
+ * "Work" shall mean the work of authorship, whether in Source or
+ * Object form, made available under the License, as indicated by a
+ * copyright notice that is included in or attached to the work
+ * (an example is provided in the Appendix below).
+ *
+ * "Derivative Works" shall mean any work, whether in Source or Object
+ * form, that is based on (or derived from) the Work and for which the
+ * editorial revisions, annotations, elaborations, or other modifications
+ * represent, as a whole, an original work of authorship. For the purposes
+ * of this License, Derivative Works shall not include works that remain
+ * separable from, or merely link (or bind by name) to the interfaces of,
+ * the Work and Derivative Works thereof.
+ *
+ * "Contribution" shall mean any work of authorship, including
+ * the original version of the Work and any modifications or additions
+ * to that Work or Derivative Works thereof, that is intentionally
+ * submitted to Licensor for inclusion in the Work by the copyright owner
+ * or by an individual or Legal Entity authorized to submit on behalf of
+ * the copyright owner. For the purposes of this definition, "submitted"
+ * means any form of electronic, verbal, or written communication sent
+ * to the Licensor or its representatives, including but not limited to
+ * communication on electronic mailing lists, source code control systems,
+ * and issue tracking systems that are managed by, or on behalf of, the
+ * Licensor for the purpose of discussing and improving the Work, but
+ * excluding communication that is conspicuously marked or otherwise
+ * designated in writing by the copyright owner as "Not a Contribution."
+ *
+ * "Contributor" shall mean Licensor and any individual or Legal Entity
+ * on behalf of whom a Contribution has been received by Licensor and
+ * subsequently incorporated within the Work.
+ *
+ * 2. Grant of Copyright License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * copyright license to reproduce, prepare Derivative Works of,
+ * publicly display, publicly perform, sublicense, and distribute the
+ * Work and such Derivative Works in Source or Object form.
+ *
+ * 3. Grant of Patent License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * (except as stated in this section) patent license to make, have made,
+ * use, offer to sell, sell, import, and otherwise transfer the Work,
+ * where such license applies only to those patent claims licensable
+ * by such Contributor that are necessarily infringed by their
+ * Contribution(s) alone or by combination of their Contribution(s)
+ * with the Work to which such Contribution(s) was submitted. If You
+ * institute patent litigation against any entity (including a
+ * cross-claim or counterclaim in a lawsuit) alleging that the Work
+ * or a Contribution incorporated within the Work constitutes direct
+ * or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate
+ * as of the date such litigation is filed.
+ *
+ * 4. Redistribution. You may reproduce and distribute copies of the
+ * Work or Derivative Works thereof in any medium, with or without
+ * modifications, and in Source or Object form, provided that You
+ * meet the following conditions:
+ *
+ * (a) You must give any other recipients of the Work or
+ * Derivative Works a copy of this License; and
+ *
+ * (b) You must cause any modified files to carry prominent notices
+ * stating that You changed the files; and
+ *
+ * (c) You must retain, in the Source form of any Derivative Works
+ * that You distribute, all copyright, patent, trademark, and
+ * attribution notices from the Source form of the Work,
+ * excluding those notices that do not pertain to any part of
+ * the Derivative Works; and
+ *
+ * (d) If the Work includes a "NOTICE" text file as part of its
+ * distribution, then any Derivative Works that You distribute must
+ * include a readable copy of the attribution notices contained
+ * within such NOTICE file, excluding those notices that do not
+ * pertain to any part of the Derivative Works, in at least one
+ * of the following places: within a NOTICE text file distributed
+ * as part of the Derivative Works; within the Source form or
+ * documentation, if provided along with the Derivative Works; or,
+ * within a display generated by the Derivative Works, if and
+ * wherever such third-party notices normally appear. The contents
+ * of the NOTICE file are for informational purposes only and
+ * do not modify the License. You may add Your own attribution
+ * notices within Derivative Works that You distribute, alongside
+ * or as an addendum to the NOTICE text from the Work, provided
+ * that such additional attribution notices cannot be construed
+ * as modifying the License.
+ *
+ * You may add Your own copyright statement to Your modifications and
+ * may provide additional or different license terms and conditions
+ * for use, reproduction, or distribution of Your modifications, or
+ * for any such Derivative Works as a whole, provided Your use,
+ * reproduction, and distribution of the Work otherwise complies with
+ * the conditions stated in this License.
+ *
+ * 5. Submission of Contributions. Unless You explicitly state otherwise,
+ * any Contribution intentionally submitted for inclusion in the Work
+ * by You to the Licensor shall be under the terms and conditions of
+ * this License, without any additional terms or conditions.
+ * Notwithstanding the above, nothing herein shall supersede or modify
+ * the terms of any separate license agreement you may have executed
+ * with Licensor regarding such Contributions.
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor,
+ * except as required for reasonable and customary use in describing the
+ * origin of the Work and reproducing the content of the NOTICE file.
+ *
+ * 7. Disclaimer of Warranty. Unless required by applicable law or
+ * agreed to in writing, Licensor provides the Work (and each
+ * Contributor provides its Contributions) on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied, including, without limitation, any warranties or conditions
+ * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ * PARTICULAR PURPOSE. You are solely responsible for determining the
+ * appropriateness of using or redistributing the Work and assume any
+ * risks associated with Your exercise of permissions under this License.
+ *
+ * 8. Limitation of Liability. In no event and under no legal theory,
+ * whether in tort (including negligence), contract, or otherwise,
+ * unless required by applicable law (such as deliberate and grossly
+ * negligent acts) or agreed to in writing, shall any Contributor be
+ * liable to You for damages, including any direct, indirect, special,
+ * incidental, or consequential damages of any character arising as a
+ * result of this License or out of the use or inability to use the
+ * Work (including but not limited to damages for loss of goodwill,
+ * work stoppage, computer failure or malfunction, or any and all
+ * other commercial damages or losses), even if such Contributor
+ * has been advised of the possibility of such damages.
+ *
+ * 9. Accepting Warranty or Additional Liability. While redistributing
+ * the Work or Derivative Works thereof, You may choose to offer,
+ * and charge a fee for, acceptance of support, warranty, indemnity,
+ * or other liability obligations and/or rights consistent with this
+ * License. However, in accepting such obligations, You may act only
+ * on Your own behalf and on Your sole responsibility, not on behalf
+ * of any other Contributor, and only if You agree to indemnify,
+ * defend, and hold each Contributor harmless for any liability
+ * incurred by, or claims asserted against, such Contributor by reason
+ * of your accepting any such warranty or additional liability.
+ *
+ * END OF TERMS AND CONDITIONS
+ *
+ * APPENDIX: How to apply the Apache License to your work.
+ *
+ * To apply the Apache License to your work, attach the following
+ * boilerplate notice, with the fields enclosed by brackets "[]"
+ * replaced with your own identifying information. (Don't include
+ * the brackets!) The text should be enclosed in the appropriate
+ * comment syntax for the file format. We also recommend that a
+ * file or class name and description of purpose be included on the
+ * same "printed page" as the copyright notice for easier
+ * identification within third-party archives.
+ *
+ * Copyright [yyyy] [name of copyright owner]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff --git a/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/readme-more.txt b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/readme-more.txt
new file mode 100644
index 000000000..f13d16e21
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/org/apache/tools/bzip2/readme-more.txt
@@ -0,0 +1,56 @@
+The library org.apache.tools.bzip2 is a library version based on the package org.apache.tools.bzip2
+of the Apache Ant 1.7 which is under the Apache License Version 2.0, January 2004, http://www.apache.org/licenses
+Ant 1.7: http://www.apache.org/dist/ant/source/apache-ant-1.7.0-src.zip
+
+Version 1.7.0.1
+ - Extended CBZip2OutputStream such that it supports the finish() method as in java.util.GZipOutputStream
+ This extension is proposed in BugZilla: http://issues.apache.org/bugzilla/show_bug.cgi?id=42713
+
+ It replaces the original close() and finalize() methods with:
+
+ /**
+ * Finishes compressing to the underlying stream without closing it,
+ * so that multiple compressors can write subsequently to the same
+ * output stream.
+ *
+ * @throws IOException
+ */
+ public void finish() throws IOException {
+ OutputStream outShadow = this.out;
+ if ( outShadow != null && this.data != null ) {
+ try {
+ if ( this.runLength > 0 ) {
+ writeRun();
+ }
+ this.currentChar = -1;
+ endBlock();
+ endCompression();
+ } finally {
+ this.data = null;
+ }
+ }
+ }
+
+ /**
+ * Overriden to close the stream.
+ */
+ protected void finalize() throws Throwable {
+ if ( this.data != null ) {
+ close();
+ super.finalize();
+ }
+ }
+
+ public void close() throws IOException {
+ finish();
+ OutputStream outShadow = this.out;
+ if ( outShadow != null ) {
+ try {
+ outShadow.close();
+ } finally {
+ this.out = null;
+ }
+ }
+
+ }
+

Back to the top