Index: src/main/java/org/apache/harmony/pack200/BandSet.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BandSet.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/BandSet.java (working copy) @@ -184,7 +184,6 @@ public long[][] parseFlags(String name, InputStream in, int counts[], BHSDCodec hiCodec, BHSDCodec loCodec) throws IOException, Pack200Exception { - // TODO Move away from decoding into a parseBand type structure int count = counts.length; if (count == 0) { return new long[][] { {} }; @@ -189,19 +188,33 @@ if (count == 0) { return new long[][] { {} }; } + int sum = 0; long[][] result = new long[count][]; - for (int j = 0; j < count; j++) { - int[] hi; - if(hiCodec != null) { - hi = decodeBandInt(name, in, hiCodec, counts[j]); - result[j] = decodeBandLong(name, in, loCodec, counts[j]); - for (int i = 0; i < counts[j]; i++) { - result[j][i] = (hi[i] << 32) |result[j][i]; + for (int i = 0; i < count; i++) { + result[i] = new long[counts[i]]; + sum += counts[i]; + } + int[] hi = null; + int[] lo; + if(hiCodec != null) { + hi = decodeBandInt(name, in, hiCodec, sum); + lo = decodeBandInt(name, in, loCodec, sum); + } else { + lo = decodeBandInt(name, in, loCodec, sum); + } + + int index = 0; + for (int i = 0; i < result.length; i++) { + for (int j = 0; j < result[i].length; j++) { + if(hi != null) { + result[i][j] = (hi[index] << 32) | lo[index]; + } else { + result[i][j] = lo[index]; } - } else { - result[j] = decodeBandLong(name, in, loCodec, counts[j]); + index++; } } + // TODO Remove debugging code debug("Parsed *" + name + " (" + result.length + ")"); return result; @@ -280,7 +293,7 @@ } // TODO Merge the decode and parsing of a multiple structure into one String[] result1 = new String[sum]; - int[] indices = decodeBandInt(name, in, codec, sum); + int[] indices = decodeBandInt(name, in, codec, sum, reference.length - 1); for (int i1 = 0; i1 < sum; i1++) { int index = indices[i1]; if (index < 0 || index >= reference.length) @@ -300,6 +313,60 @@ return result; } + private int[] decodeBandInt(String name, InputStream in, BHSDCodec codec, int count, int maxValue) throws IOException, Pack200Exception { + long[] band; + Codec codecUsed = codec; + if (codec.getB() == 1 || count == 0) { + band = codec.decode(count, in); + } else { + long[] getFirst = codec.decode(1, in); + if (getFirst.length == 0) { + return new int[0]; + } + long first = getFirst[0]; + if (codec.isSigned() && first >= -256 && first <= -1) { + // Non-default codec should be used + codecUsed = CodecEncoding.getCodec((int) (-1 - first), + header.getBandHeadersInputStream(), codec); + band = codecUsed.decode(count, in); + } else if (!codec.isSigned() && first >= codec.getL() + && first <= codec.getL() + 255) { + // Non-default codec should be used + codecUsed = CodecEncoding.getCodec((int) first + - codec.getL(), header.getBandHeadersInputStream(), codec); + band = codecUsed.decode(count, in); + } else { + // First element should not be discarded + band = codec.decode(count - 1, in, first); + } + } + + int[] returnBand = new int[band.length]; + for (int i = 0; i < returnBand.length; i++) { + returnBand[i] = (int)band[i]; + } + + /* + * Note - this is not in the spec, but seems to be used as an + * optimization by the RI for bands where the minimum and maximum values + * are known (ie reference bands). It will not hurt any encoding that is + * following the spec because all the values decoded will be inside the + * range anyway. + */ + if (codecUsed instanceof BHSDCodec) { + for (int i = 0; i < returnBand.length; i++) { + while (returnBand[i] < 0) { + returnBand[i] += ((BHSDCodec) codecUsed).cardinality(); + } + while (returnBand[i] > maxValue) { + returnBand[i] -= ((BHSDCodec) codecUsed).cardinality(); + } + } + } + + return returnBand; + } + /** * This is a local debugging message to aid the developer in writing this * class. It will be removed before going into production. If the property Index: src/main/java/org/apache/harmony/pack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy) @@ -20,6 +20,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.ConstantValueAttribute; @@ -233,7 +234,7 @@ if ((flag & (1 << 16)) != 0) methodAttrCount++; } - } + } int[] methodAttrCounts = decodeBandInt("method_attr_count", in, Codec.UNSIGNED5, methodAttrCount); int[][] methodAttrIndexes = decodeBandInt("method_attr_indexes", in, Codec.UNSIGNED5, methodAttrCounts); int callCount = 0; @@ -424,7 +425,7 @@ sourceFileIndex++; } if(enclosingMethodLayout.matches(flag)) { - // TODO + // TODO } if(signatureLayout.matches(flag)) { // TODO @@ -510,7 +511,6 @@ if ((flag & (1 << 16)) != 0) codeAttrCount++; } - System.out.println("codeAttrCount = " + codeAttrCount); int[] codeAttrCounts = decodeBandInt("code_attr_count", in, Codec.UNSIGNED5, codeAttrCount); int[][] codeAttrIndexes = decodeBandInt("code_attr_indexes", in, Codec.UNSIGNED5, codeAttrCounts); int callCount = 0; @@ -521,11 +521,9 @@ callCount += layout.numBackwardsCallables(); } } - System.out.println("callCount = " + callCount); int[] codeAttrCalls = decodeBandInt("code_attr_calls", in, Codec.UNSIGNED5, callCount); int lineNumberTableCount = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE, AttributeLayout.CONTEXT_CODE)); - System.out.println("lineNumberTables = " + lineNumberTableCount); int[] lineNumberTableN = decodeBandInt("code_LineNumberTable_N", in, Codec.UNSIGNED5, lineNumberTableCount); int[][] lineNumberTableBciP = decodeBandInt("code_LineNumberTable_bci_P", in, Codec.BCI5, lineNumberTableN); int[][] lineNumberTableLine = decodeBandInt("code_LineNumberTable_line", in, Codec.UNSIGNED5, lineNumberTableN); @@ -533,7 +531,6 @@ for (int i = 0; i < types.length; i++) { String type = types[i]; int lengthNBand = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(type, AttributeLayout.CONTEXT_CODE)); - System.out.println(type + " count = " + lengthNBand); int[] nBand = decodeBandInt("code_" + type + "_N", in, Codec.UNSIGNED5, lengthNBand); int[][] bciP = decodeBandInt("code_" + type + "_bci_P", in, Codec.BCI5, nBand); Index: src/main/java/org/apache/harmony/pack200/CodecEncoding.java =================================================================== --- src/main/java/org/apache/harmony/pack200/CodecEncoding.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/CodecEncoding.java (working copy) @@ -95,7 +95,7 @@ * @throws IOException if there is a problem reading from the input stream (which * in reality, is never, since the band_headers are likely stored in a byte array * and accessed via a ByteArrayInputStream. However, an EOFException could occur - * if things go titsup.com. + * if things go wrong) * @throws Pack200Exception */ public static Codec getCodec(int value, InputStream in, Codec defaultCodec) throws IOException, Pack200Exception { @@ -151,7 +151,7 @@ boolean fdef = (offset & 1) == 1; boolean udef = (offset >> 1 & 1) == 1; int tdefl = offset >> 2; - boolean tdef = tdefl == 0; + boolean tdef = tdefl != 0; // From section 6.7.3 of spec final int[] tdefToL= {0,4,8,16,32,64,128,192,224,240,248,252 }; int l = tdefToL[tdefl]; Index: src/main/java/org/apache/harmony/pack200/CpBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/CpBands.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/CpBands.java (working copy) @@ -313,57 +313,53 @@ private void parseCpUtf8(InputStream in) throws IOException, Pack200Exception { - int cpUTF8Count = header.getCpUTF8Count(); - // TODO Update codec.decode -> decodeScalar + int cpUTF8Count = header.getCpUTF8Count(); cpUTF8 = new String[cpUTF8Count]; cpUTF8[0] = ""; //$NON-NLS-1$ - int[] suffix = new int[cpUTF8Count]; - long last = 0; int[] prefix = decodeBandInt("cpUTF8Prefix", in, Codec.DELTA5, cpUTF8Count-2); - int chars = 0; - int bigSuffix = 0; - for (int i = 1; i < cpUTF8Count; i++) { - last = suffix[i] = (int) Codec.UNSIGNED5.decode(in); - if (last == 0) { - bigSuffix++; + int charCount = 0; + int bigSuffixCount = 0; + int[] suffix = decodeBandInt("cpUTF8Suffix", in, Codec.UNSIGNED5, cpUTF8Count-1); + + for (int i = 0; i < suffix.length; i++) { + if (suffix[i] == 0) { + bigSuffixCount++; } else { - chars += last; + charCount += suffix[i]; } } - char data[] = new char[chars]; + char[] data = new char[charCount]; + int[] dataBand = decodeBandInt("cp_Utf8_chars", in, Codec.CHAR3, charCount); for (int i = 0; i < data.length; i++) { - data[i] = (char) Codec.CHAR3.decode(in); - } - // read in the big suffix data - char bigSuffixData[][] = new char[bigSuffix][]; - last = 0; - for (int i = 0; i < bigSuffix; i++) { - last = (int) Codec.DELTA5.decode(in, last); - bigSuffixData[i] = new char[(int) last]; - } - // initialize big suffix data - for (int i = 0; i < bigSuffix; i++) { - char[] singleBigSuffixData = bigSuffixData[i]; - last = 0; - for (int j = 0; j < singleBigSuffixData.length; j++) { - last = singleBigSuffixData[j] = (char) Codec.DELTA5.decode(in, - last); + data[i] = (char) dataBand[i]; + } + + // Read in the big suffix data + int[] bigSuffixCounts = decodeBandInt("cp_Utf8_big_suffix", in, Codec.DELTA5, bigSuffixCount); + int[][] bigSuffixDataBand = decodeBandInt("cp_Utf8_big_chars", in, Codec.DELTA5, bigSuffixCounts); + + // Convert big suffix data to characters + char bigSuffixData[][] = new char[bigSuffixCount][]; + for (int i = 0; i < bigSuffixDataBand.length; i++) { + bigSuffixData[i] = new char[bigSuffixDataBand[i].length]; + for (int j = 0; j < bigSuffixDataBand[i].length; j++) { + bigSuffixData[i][j] = (char) bigSuffixDataBand[i][j]; } } - // go through the strings - chars = 0; - bigSuffix = 0; + // Go through the strings + charCount = 0; + bigSuffixCount = 0; for (int i = 1; i < cpUTF8Count; i++) { String lastString = cpUTF8[i - 1]; - if (suffix[i] == 0) { + if (suffix[i-1] == 0) { // The big suffix stuff hasn't been tested, and I'll be // surprised if it works first time w/o errors ... cpUTF8[i] = lastString.substring(0, i>1 ? prefix[i-2] : 0) - + new String(bigSuffixData[bigSuffix++]); + + new String(bigSuffixData[bigSuffixCount++]); } else { cpUTF8[i] = lastString.substring(0, i>1 ? prefix[i-2]: 0) - + new String(data, chars, suffix[i]); - chars += suffix[i]; + + new String(data, charCount, suffix[i-1]); + charCount += suffix[i-1]; } } } Index: src/main/java/org/apache/harmony/pack200/PopulationCodec.java =================================================================== --- src/main/java/org/apache/harmony/pack200/PopulationCodec.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/PopulationCodec.java (working copy) @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; public class PopulationCodec extends Codec { private Codec favouredCodec; @@ -91,15 +92,15 @@ // read favorites result = tokenCodec.decode(n, in); // read unfavorites - last = 0; - for(int i=0;i