Author: sjanuary
Date: Fri Jun 12 08:35:08 2009
New Revision: 784030
URL: http://svn.apache.org/viewvc?rev=784030&view=rev
Log:
Pack200 - support for -E option (different effort compression algorithms)
Added:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java (with props)
Modified:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java Fri Jun 12 08:35:08 2009
@@ -204,14 +204,14 @@
return cardinality;
}
- public long decode(InputStream in) throws IOException, Pack200Exception {
+ public int decode(InputStream in) throws IOException, Pack200Exception {
if (d != 0)
throw new Pack200Exception(
"Delta encoding used without passing in last value; this is a coding error");
return decode(in, 0);
}
- public long decode(InputStream in, long last) throws IOException,
+ public int decode(InputStream in, long last) throws IOException,
Pack200Exception {
int n = 0;
long z = 0;
@@ -219,6 +219,7 @@
do {
x = in.read();
+ lastBandLength ++;
z += x * powers[n];
n++;
} while (x >= l && n < b);
@@ -252,7 +253,39 @@
// }
if (isDelta())
z += last;
- return z;
+ return (int)z;
+ }
+
+ public int[] decodeInts(int n, InputStream in) throws IOException,
+ Pack200Exception {
+ int[] band = super.decodeInts(n, in);
+ if (isDelta()) {
+ for (int i = 0; i < band.length; i++) {
+ while (band[i] > largest) {
+ band[i] -= cardinality;
+ }
+ while (band[i] < smallest) {
+ band[i] += cardinality;
+ }
+ }
+ }
+ return band;
+ }
+
+ public int[] decodeInts(int n, InputStream in, int firstValue)
+ throws IOException, Pack200Exception {
+ int[] band = super.decodeInts(n, in, firstValue);
+ if (isDelta()) {
+ for (int i = 0; i < band.length; i++) {
+ while (band[i] > largest) {
+ band[i] -= cardinality;
+ }
+ while (band[i] < smallest) {
+ band[i] += cardinality;
+ }
+ }
+ }
+ return band;
}
// private long cast32(long u) {
@@ -269,19 +302,19 @@
* @return true if the encoding can encode this value
*/
public boolean encodes(long value) {
- return (value >= smallest && value <= largest);
+ return value >= smallest && value <= largest;
}
- public byte[] encode(long value, long last) throws Pack200Exception {
- if (isDelta()) {
- value -= last;
+ public byte[] encode(int value, int last) throws Pack200Exception {
+ if(!encodes(value)) {
+ throw new Pack200Exception("The codec " + toString()
+ + " does not encode the value " + value);
}
- // TODO: Do we need this? this implementation isn't right because of integer overflow...
-// if (!encodes(value)) {
-// throw new Pack200Exception("The codec " + toString()
-// + " does not encode the value " + value);
-// }
+
long z = value;
+ if (isDelta()) {
+ z -= last;
+ }
if (isSigned()) {
if(z < Integer.MIN_VALUE) {
z += 4294967296L;
@@ -301,12 +334,16 @@
if (z < 0) {
// Need to use integer overflow here to represent negatives.
if(cardinality < 4294967296L) {
- z+= cardinality;
+ z += cardinality;
} else {
z += 4294967296L; // this value is equal to (1 << 32).
}
}
}
+ if (z < 0) {
+ throw new Pack200Exception("unable to encode");
+ }
+
List byteList = new ArrayList();
for (int n = 0; n < b; n++) {
long byteN;
@@ -331,7 +368,7 @@
return bytes;
}
- public byte[] encode(long value) throws Pack200Exception {
+ public byte[] encode(int value) throws Pack200Exception {
return encode(value, 0);
}
@@ -393,19 +430,16 @@
private long calculateSmallest() {
long result;
- if (d == 1) {
- BHSDCodec bh0 = new BHSDCodec(b, h);
- return bh0.smallest();
- } else if (isSigned()) {
- result = -cardinality() / (1 << s);
- } else {
- if (cardinality > Integer.MAX_VALUE) {
+ if (d == 1 || !isSigned()) {
+ if (cardinality >= 4294967296L) { // 2^32
result = Integer.MIN_VALUE;
} else {
result = 0;
}
+ } else {
+ result = Math.max(Integer.MIN_VALUE, -cardinality() / (1 << s));
}
- return Math.max(Integer.MIN_VALUE, result);
+ return result;
}
/**
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java Fri Jun 12 08:35:08 2009
@@ -18,13 +18,26 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
public abstract class BandSet {
- private final int effort;
protected final SegmentHeader segmentHeader;
+ private final int effort;
+
+ // Minimum size of band for each effort level where we consider alternative codecs
+ // Note: these values have been tuned - please test carefully if changing them
+ private final int[] effortThresholds = new int[] {0, 0, 1000, 500, 100, 100, 100, 100, 100, 0};
+
+ private long[] canonicalLargest;
+ private long[] canonicalSmallest;
public BandSet(int effort, SegmentHeader header) {
this.effort = effort;
@@ -42,25 +55,36 @@
}
public byte[] encodeBandInt(String name, int[] ints, BHSDCodec defaultCodec) throws Pack200Exception {
- if(effort > 1 && (ints.length > 99 || effort == 9)) {
- Codec betterCodec = lookForBetterCodec(name, ints, defaultCodec);
+ byte[] encodedBand = null;
+ if(effort > 1 && (ints.length >= effortThresholds[effort])) {
+ BandAnalysisResults results = analyseBand(name, ints, defaultCodec);
+ Codec betterCodec = results.betterCodec;
+ encodedBand = results.encodedBand;
if(betterCodec != null) {
if(betterCodec instanceof BHSDCodec) {
int[] specifierBand = CodecEncoding.getSpecifier(betterCodec, defaultCodec);
int specifier = specifierBand[0];
- if(specifierBand.length > 0) {
+ if(specifierBand.length > 1) {
for (int i = 1; i < specifierBand.length; i++) {
segmentHeader.appendBandCodingSpecifier(specifierBand[i]);
}
}
+ if(defaultCodec.isSigned()) {
+ specifier = -1 -specifier;
+ } else {
+ specifier = specifier + defaultCodec.getL();
+ }
byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier});
- byte[] rest = betterCodec.encode(ints);
- byte[] band = new byte[specifierEncoded.length + rest.length];
+ byte[] band = new byte[specifierEncoded.length + encodedBand.length];
System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length);
- System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length);
+ System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length);
return band;
} else if (betterCodec instanceof PopulationCodec) {
-
+ int[] extraSpecifierInfo = results.extraMetadata;
+ for (int i = 0; i < extraSpecifierInfo.length; i++) {
+ segmentHeader.appendBandCodingSpecifier(extraSpecifierInfo[i]);
+ }
+ return encodedBand;
} else if (betterCodec instanceof RunCodec) {
}
@@ -69,37 +93,201 @@
// If we get here then we've decided to use the default codec.
if(ints.length > 0) {
-// System.out.println("encoding " + name + ", size = " + ints.length);
+ if(encodedBand == null) {
+ encodedBand = defaultCodec.encode(ints);
+ }
int first = ints[0];
if(defaultCodec.getB() != 1) {
if (defaultCodec.isSigned() && first >= -256 && first <= -1) {
int specifier = -1 - CodecEncoding.getSpecifierForDefaultCodec(defaultCodec);
byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier});
- byte[] rest = defaultCodec.encode(ints);
- byte[] band = new byte[specifierEncoded.length + rest.length];
+ byte[] band = new byte[specifierEncoded.length + encodedBand.length];
System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length);
- System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length);
+ System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length);
return band;
} else if (!defaultCodec.isSigned() && first >= defaultCodec.getL()
&& first <= defaultCodec.getL() + 255) {
int specifier = CodecEncoding.getSpecifierForDefaultCodec(defaultCodec) + defaultCodec.getL();
byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier});
- byte[] rest = defaultCodec.encode(ints);
- byte[] band = new byte[specifierEncoded.length + rest.length];
+ byte[] band = new byte[specifierEncoded.length + encodedBand.length];
System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length);
- System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length);
+ System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length);
return band;
}
}
- return defaultCodec.encode(ints);
+ return encodedBand;
}
return new byte[0];
}
- private Codec lookForBetterCodec(String name, int[] ints,
- BHSDCodec defaultCodec) {
- // TODO Auto-generated method stub
- return null;
+ private BandAnalysisResults analyseBand(String name, int[] band,
+ BHSDCodec defaultCodec) throws Pack200Exception {
+
+ BandAnalysisResults results = new BandAnalysisResults();
+
+ if(canonicalLargest == null) {
+ canonicalLargest = new long[116];
+ canonicalSmallest = new long[116];
+ for (int i = 1; i < canonicalLargest.length; i++) {
+ canonicalLargest[i] = CodecEncoding.getCanonicalCodec(i).largest();
+ canonicalSmallest[i] = CodecEncoding.getCanonicalCodec(i).smallest();
+ }
+ }
+ BandData bandData = new BandData(band);
+
+ // Check that there is a reasonable saving to be made
+ byte[] encoded = defaultCodec.encode(band);
+ results.encodedBand = encoded;
+
+ // Note: these values have been tuned - please test carefully if changing them
+ if(encoded.length <= band.length + 23 - 2*effort) { // TODO: tweak
+ return results;
+ }
+
+ // Check if we can use BYTE1 as that's a 1:1 mapping if we can
+ if(!bandData.anyNegatives() && bandData.largest <= Codec.BYTE1.largest()) {
+ results.encodedBand = Codec.BYTE1.encode(band) ;
+ results.betterCodec = Codec.BYTE1;
+ return results;
+ }
+
+ // Consider a population codec (but can't be nested)
+ if(effort > 3 && !name.equals("POPULATION")) {
+ int numDistinctValues = bandData.numDistinctValues();
+ float distinctValuesAsProportion = (float)numDistinctValues / (float)band.length;
+
+ // Note: these values have been tuned - please test carefully if changing them
+ if(numDistinctValues < 100 || distinctValuesAsProportion < 0.02 || (effort > 6 && distinctValuesAsProportion < 0.04)) { // TODO: tweak
+ encodeWithPopulationCodec(name, band, defaultCodec, bandData, results);
+ if(timeToStop(results)) {
+ return results;
+ }
+ }
+ }
+
+ List codecFamiliesToTry = new ArrayList();
+
+ // See if the deltas are mainly small increments
+ if(bandData.mainlyPositiveDeltas() && bandData.mainlySmallDeltas()) {
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs2);
+ }
+
+ if (bandData.wellCorrelated()) { // Try delta encodings
+ if (bandData.mainlyPositiveDeltas()) {
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs5);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2);
+ } else {
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs2);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs5);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs2);
+ }
+ } else {
+ if (bandData.anyNegatives()) {
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs2);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs2);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs5);
+ } else {
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs1);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs3);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs4);
+ codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs5);
+ }
+ }
+ if(name.equalsIgnoreCase("cpint")) {
+ System.out.print("");
+ }
+
+ for (Iterator iterator = codecFamiliesToTry.iterator(); iterator
+ .hasNext();) {
+ BHSDCodec[] family = (BHSDCodec[]) iterator.next();
+ tryCodecs(name, band, defaultCodec, bandData, results, encoded,
+ family);
+ if (timeToStop(results)) {
+ break;
+ }
+ }
+
+ return results;
+ }
+
+
+ private boolean timeToStop(BandAnalysisResults results) {
+ // if tried more than effort number of codecs for this band then return
+ // Note: these values have been tuned - please test carefully if changing them
+ if(effort > 6) {
+ return results.numCodecsTried >= effort * 2;
+ }
+ return results.numCodecsTried >= effort;
+ // May want to also check how much we've saved if performance needs improving, e.g. saved more than effort*2 %
+ // || (float)results.saved/(float)results.encodedBand.length > (float)effort * 2/100;
+ }
+
+ private void tryCodecs(String name, int[] band, BHSDCodec defaultCodec, BandData bandData,
+ BandAnalysisResults results, byte[] encoded,
+ BHSDCodec[] potentialCodecs) throws Pack200Exception {
+ for (int i = 0; i < potentialCodecs.length; i++) {
+ BHSDCodec potential = potentialCodecs[i];
+ if(potential.equals(defaultCodec)) {
+ return; // don't try codecs with greater cardinality in the same 'family' as the default codec as there won't be any savings
+ }
+ if (potential.isDelta()) {
+ if (potential.largest() >= bandData.largestDelta
+ && potential.smallest() <= bandData.smallestDelta
+ && potential.largest() >= bandData.largest
+ && potential.smallest() <= bandData.smallest) {
+ // TODO: can represent some negative deltas with overflow
+ byte[] encoded2 = potential.encode(band);
+ results.numCodecsTried++;
+ results.codecsTried.add(potential);
+ byte[] specifierEncoded = defaultCodec.encode(CodecEncoding
+ .getSpecifier(potential, null));
+ int saved = encoded.length - encoded2.length
+ - specifierEncoded.length;
+ if (saved > results.saved) {
+ results.betterCodec = potential;
+ results.encodedBand = encoded2;
+ results.saved = saved;
+ }
+ }
+ } else if (potential.largest() >= bandData.largest
+ && potential.smallest() <= bandData.smallest) {
+ byte[] encoded2 = potential.encode(band);
+ results.numCodecsTried++;
+ results.codecsTried.add(potential);
+ byte[] specifierEncoded = defaultCodec.encode(CodecEncoding
+ .getSpecifier(potential, null));
+ int saved = encoded.length - encoded2.length
+ - specifierEncoded.length;
+ if (saved > results.saved) {
+ results.betterCodec = potential;
+ results.encodedBand = encoded2;
+ results.saved = saved;
+ }
+ }
+ if(timeToStop(results)) {
+ return;
+ }
+ }
}
public boolean isPredictableSourceFileName(String className, String sourceFileName) {
@@ -113,6 +301,201 @@
return className.equals(sourceFileName);
}
+// This could be useful if further enhancements are done but is not currently used
+//
+// private void encodeWithRunCodec(String name, int[] band, int index,
+// BHSDCodec defaultCodec, BandData bandData,
+// BandAnalysisResults results) throws Pack200Exception {
+// int[] firstBand = new int[index];
+// int[] secondBand = new int[band.length - index];
+// System.arraycopy(band, 0, firstBand, 0, index);
+// System.arraycopy(band, index, secondBand, 0, secondBand.length);
+// BandAnalysisResults firstResults = analyseBand(name + "A", firstBand, defaultCodec);
+// BandAnalysisResults secondResults = analyseBand(name + "B", secondBand, defaultCodec);
+// int specifier = 117;
+// byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier});
+// int totalLength = firstResults.encodedBand.length + secondResults.encodedBand.length + specifierEncoded.length + 4; // TODO actual
+// if(totalLength < results.encodedBand.length) {
+// System.out.println("using run codec");
+// results.saved += results.encodedBand.length - totalLength;
+// byte[] encodedBand = new byte[specifierEncoded.length + firstResults.encodedBand.length + secondResults.encodedBand.length];
+// System.arraycopy(specifierEncoded, 0, encodedBand, 0, specifierEncoded.length);
+// System.arraycopy(firstResults.encodedBand, 0, encodedBand, specifierEncoded.length, firstResults.encodedBand.length);
+// System.arraycopy(secondResults.encodedBand, 0, encodedBand, specifierEncoded.length + firstResults.encodedBand.length, secondResults.encodedBand.length);
+// results.encodedBand = encodedBand;
+// results.betterCodec = new RunCodec(index, firstResults.betterCodec, secondResults.betterCodec);
+// }
+// }
+
+ private void encodeWithPopulationCodec(String name, int[] band,
+ BHSDCodec defaultCodec, BandData bandData, BandAnalysisResults results) throws Pack200Exception {
+ results.numCodecsTried += 3; // quite a bit more effort to try this codec
+ final Map distinctValues = bandData.distinctValues;
+
+ List favoured = new ArrayList();
+ for (Iterator iterator = distinctValues.keySet().iterator(); iterator
+ .hasNext();) {
+ Integer value = (Integer) iterator.next();
+ Integer count = (Integer) distinctValues.get(value);
+ if(count.intValue() > 2 || distinctValues.size() < 256) { // TODO: tweak
+ favoured.add(value);
+ }
+ }
+
+ // Sort the favoured list with the most commonly occurring first
+ if(distinctValues.size() > 255) {
+ Collections.sort(favoured, new Comparator() {
+ public int compare(Object arg0, Object arg1) {
+ return ((Integer)distinctValues.get(arg1)).compareTo((Integer)distinctValues.get(arg0));
+ }
+ });
+ }
+
+ IntList unfavoured = new IntList();
+ Map favouredToIndex = new HashMap();
+ for (int i = 0; i < favoured.size(); i++) {
+ Integer value = (Integer) favoured.get(i);
+ favouredToIndex.put(value, new Integer(i));
+ }
+
+ int[] tokens = new int[band.length];
+ for (int i = 0; i < band.length; i++) {
+ Integer favouredIndex = (Integer)favouredToIndex.get(new Integer(band[i]));
+ if(favouredIndex == null) {
+ tokens[i] = 0;
+ unfavoured.add(band[i]);
+ } else {
+ tokens[i] = favouredIndex.intValue() + 1;
+ }
+ }
+ favoured.add(favoured.get(favoured.size() - 1)); // repeat last value
+ int[] favouredBand = listToArray(favoured);
+ int[] unfavouredBand = unfavoured.toArray();
+
+ // Analyse the three bands to get the best codec
+ BandAnalysisResults favouredResults = analyseBand("POPULATION", favouredBand, defaultCodec);
+ BandAnalysisResults unfavouredResults = analyseBand("POPULATION", unfavouredBand, defaultCodec);
+
+ int tdefL = 0;
+ int l = 0;
+ Codec tokenCodec = null;
+ byte[] tokensEncoded;
+ int k = favoured.size() - 1;
+ if(k < 256) {
+ tdefL = 1;
+ tokensEncoded = Codec.BYTE1.encode(tokens);
+ } else {
+ BandAnalysisResults tokenResults = analyseBand("POPULATION", tokens, defaultCodec);
+ tokenCodec = tokenResults.betterCodec;
+ tokensEncoded = tokenResults.encodedBand;
+ if(tokenCodec == null) {
+ tokenCodec = defaultCodec;
+ }
+ l = ((BHSDCodec) tokenCodec).getL();
+ int h = ((BHSDCodec) tokenCodec).getH();
+ int s = ((BHSDCodec) tokenCodec).getS();
+ int b = ((BHSDCodec) tokenCodec).getB();
+ int d = ((BHSDCodec) tokenCodec).isDelta() ? 1 : 0;
+ if(s == 0 && d == 0) {
+ boolean canUseTDefL = true;
+ if(b > 1) {
+ BHSDCodec oneLowerB = new BHSDCodec(b-1, h);
+ if(oneLowerB.largest() >= k) {
+ canUseTDefL = false;
+ }
+ }
+ if(canUseTDefL) {
+ switch (l) {
+ case 4:
+ tdefL = 1;
+ break;
+ case 8:
+ tdefL = 2;
+ break;
+ case 16:
+ tdefL = 3;
+ break;
+ case 32:
+ tdefL = 4;
+ break;
+ case 64:
+ tdefL = 5;
+ break;
+ case 128:
+ tdefL = 6;
+ break;
+ case 192:
+ tdefL = 7;
+ break;
+ case 224:
+ tdefL = 8;
+ break;
+ case 240:
+ tdefL = 9;
+ break;
+ case 248:
+ tdefL = 10;
+ break;
+ case 252:
+ tdefL = 11;
+ break;
+ }
+ }
+ }
+ }
+
+ byte[] favouredEncoded = favouredResults.encodedBand;
+ byte[] unfavouredEncoded = unfavouredResults.encodedBand;
+ Codec favouredCodec = favouredResults.betterCodec;
+ Codec unfavouredCodec = unfavouredResults.betterCodec;
+
+ int specifier = 141 + (favouredCodec == null ? 1 : 0) + (4 * tdefL) + (unfavouredCodec == null ? 2 : 0);
+ IntList extraBandMetadata = new IntList(3);
+ if(favouredCodec != null) {
+ int[] specifiers = CodecEncoding.getSpecifier(favouredCodec, null);
+ for (int i = 0; i < specifiers.length; i++) {
+ extraBandMetadata.add(specifiers[i]);
+ }
+ }
+ if(tdefL == 0) {
+ int[] specifiers = CodecEncoding.getSpecifier(tokenCodec, null);
+ for (int i = 0; i < specifiers.length; i++) {
+ extraBandMetadata.add(specifiers[i]);
+ }
+ }
+ if(unfavouredCodec != null) {
+ int[] specifiers = CodecEncoding.getSpecifier(unfavouredCodec, null);
+ for (int i = 0; i < specifiers.length; i++) {
+ extraBandMetadata.add(specifiers[i]);
+ }
+ }
+ int[] extraMetadata = extraBandMetadata.toArray();
+ byte[] extraMetadataEncoded = Codec.UNSIGNED5.encode(extraMetadata);
+ if(defaultCodec.isSigned()) {
+ specifier = -1 -specifier;
+ } else {
+ specifier = specifier + defaultCodec.getL();
+ }
+ byte[] firstValueEncoded = defaultCodec.encode(new int[] {specifier});
+ int totalBandLength = firstValueEncoded.length + favouredEncoded.length + tokensEncoded.length + unfavouredEncoded.length;
+
+ if(totalBandLength + extraMetadataEncoded.length < results.encodedBand.length) {
+ results.saved += results.encodedBand.length - (totalBandLength + extraMetadataEncoded.length);
+ byte[] encodedBand = new byte[totalBandLength];
+ System.arraycopy(firstValueEncoded, 0, encodedBand, 0, firstValueEncoded.length);
+ System.arraycopy(favouredEncoded, 0, encodedBand, firstValueEncoded.length, favouredEncoded.length);
+ System.arraycopy(tokensEncoded, 0, encodedBand, firstValueEncoded.length + favouredEncoded.length, tokensEncoded.length);
+ System.arraycopy(unfavouredEncoded, 0, encodedBand, firstValueEncoded.length + favouredEncoded.length + tokensEncoded.length, unfavouredEncoded.length);
+ results.encodedBand = encodedBand;
+ results.extraMetadata = extraMetadata;
+ if(l != 0) {
+ results.betterCodec = new PopulationCodec(favouredCodec, l, unfavouredCodec);
+ } else {
+ results.betterCodec = new PopulationCodec(favouredCodec, tokenCodec, unfavouredCodec);
+ }
+ }
+ }
+
protected byte[] encodeFlags(String name, long[] flags, BHSDCodec loCodec, BHSDCodec hiCodec,
boolean haveHiFlags) throws Pack200Exception {
if(!haveHiFlags) {
@@ -199,4 +582,112 @@
return flatArray;
}
+ /**
+ * BandData represents information about a band, e.g. largest value etc
+ * and is used in the heuristics that calculate whether an alternative
+ * Codec could make the encoded band smaller.
+ */
+ public class BandData {
+
+ private final int[] band;
+ private int smallest = Integer.MAX_VALUE;
+ private int largest = Integer.MIN_VALUE;
+ private int smallestDelta;
+ private int largestDelta;
+
+ private int deltaIsAscending = 0;
+ private int smallDeltaCount = 0;
+
+ private double averageAbsoluteDelta = 0;
+ private double averageAbsoluteValue = 0;
+
+ private Map distinctValues;
+
+ public BandData(int[] band) {
+ this.band = band;
+ Integer one = new Integer(1);
+ for (int i = 0; i < band.length; i++) {
+ if(band[i] < smallest) {
+ smallest = band[i];
+ }
+ if(band[i] > largest) {
+ largest = band[i];
+ }
+ if(i != 0) {
+ int delta = band[i] - band[i - 1];
+ if(delta < smallestDelta) {
+ smallestDelta = delta;
+ }
+ if(delta > largestDelta) {
+ largestDelta = delta;
+ }
+ if(delta >= 0) {
+ deltaIsAscending++;
+ }
+ averageAbsoluteDelta += (double)Math.abs(delta)/(double)(band.length - 1);
+ if(Math.abs(delta) < 256) {
+ smallDeltaCount++;
+ }
+ } else {
+ smallestDelta = band[0];
+ largestDelta = band[0];
+ }
+ averageAbsoluteValue += (double)Math.abs(band[i])/(double)band.length;
+ if(effort > 3) { // do calculations needed to consider population codec
+ if(distinctValues == null) {
+ distinctValues = new HashMap();
+ }
+ Integer value = new Integer(band[i]);
+ Integer count = (Integer) distinctValues.get(value);
+ if(count == null) {
+ count = one;
+ } else {
+ count = new Integer(count.intValue() + 1);
+ }
+ distinctValues.put(value, count);
+ }
+ }
+ }
+
+ public boolean mainlySmallDeltas() {
+ // Note: the value below has been tuned - please test carefully if changing it
+ return (float)smallDeltaCount/(float)band.length > 0.7F;
+ }
+ public boolean wellCorrelated() {
+ // Note: the value below has been tuned - please test carefully if changing it
+ return averageAbsoluteDelta * 3.1 < averageAbsoluteValue;
+ }
+
+ public boolean mainlyPositiveDeltas() {
+ // Note: the value below has been tuned - please test carefully if changing it
+ return (float)deltaIsAscending/(float)band.length > 0.95F;
+ }
+
+ public boolean anyNegatives() {
+ return smallest < 0;
+ }
+
+ public int numDistinctValues() {
+ if(distinctValues == null) {
+ return band.length;
+ }
+ return distinctValues.size();
+ }
+
+ }
+
+ public class BandAnalysisResults {
+
+ private final List codecsTried = new ArrayList(effort);
+
+ private int numCodecsTried = 0;
+ private int saved = 0;
+
+ private int[] extraMetadata;
+
+ private byte[] encodedBand;
+ private Codec betterCodec;
+
+ }
+
}
Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java?rev=784030&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java (added)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java Fri Jun 12 08:35:08 2009
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+package org.apache.harmony.pack200;
+
+/**
+ * Sets of codecs that share characteristics. Mainly used for different effort
+ * compression heuristics in BandSet.
+ */
+public class CanonicalCodecFamilies {
+
+ // Families of codecs for bands of positive integers that do not correlate
+ // well (i.e. would not benefit from delta encoding)
+
+ public static BHSDCodec[] nonDeltaUnsignedCodecs1 = new BHSDCodec[] {
+ // (1,256) is a special case and is considered separately so shouldn't be included here
+// CodecEncoding.getCanonicalCodec(1), // (1,256)
+ CodecEncoding.getCanonicalCodec(5), // (2,256)
+ CodecEncoding.getCanonicalCodec(9), // (3,256)
+ CodecEncoding.getCanonicalCodec(13) // (4,256)
+ };
+
+ public static BHSDCodec[] nonDeltaUnsignedCodecs2 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(17), // (5,4)
+ CodecEncoding.getCanonicalCodec(20), // (5,16)
+ CodecEncoding.getCanonicalCodec(23), // (5,32)
+ CodecEncoding.getCanonicalCodec(26), // (5,64)
+ CodecEncoding.getCanonicalCodec(29) // (5,128)
+ };
+
+ public static BHSDCodec[] nonDeltaUnsignedCodecs3 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(47), // (2,192)
+ CodecEncoding.getCanonicalCodec(48), // (2,224)
+ CodecEncoding.getCanonicalCodec(49), // (2,240)
+ CodecEncoding.getCanonicalCodec(50), // (2,248)
+ CodecEncoding.getCanonicalCodec(51) // (2,252)
+ };
+
+ public static BHSDCodec[] nonDeltaUnsignedCodecs4 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(70), // (3,192)
+ CodecEncoding.getCanonicalCodec(71), // (3,224)
+ CodecEncoding.getCanonicalCodec(72), // (3,240)
+ CodecEncoding.getCanonicalCodec(73), // (3,248)
+ CodecEncoding.getCanonicalCodec(74) // (3,252)
+ };
+
+ public static BHSDCodec[] nonDeltaUnsignedCodecs5 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(93), // (4,192)
+ CodecEncoding.getCanonicalCodec(94), // (4,224)
+ CodecEncoding.getCanonicalCodec(95), // (4,240)
+ CodecEncoding.getCanonicalCodec(96), // (4,248)
+ CodecEncoding.getCanonicalCodec(97) // (4,252)
+ };
+
+ // Families of codecs for bands of positive integers that do correlate well
+ // and would benefit from delta encoding
+
+ public static BHSDCodec[] deltaUnsignedCodecs1 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(3), // (1,256,0,1)
+ CodecEncoding.getCanonicalCodec(7), // (2,256,0,1)
+ CodecEncoding.getCanonicalCodec(11), // (3,256,0,1)
+ CodecEncoding.getCanonicalCodec(15) // (4,256,0,1)
+ };
+
+ public static BHSDCodec[] deltaUnsignedCodecs2 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(32), // (5,4,0,1)
+ CodecEncoding.getCanonicalCodec(35), // (5,16,0,1)
+ CodecEncoding.getCanonicalCodec(38), // (5,32,0,1)
+ CodecEncoding.getCanonicalCodec(41), // (5,64,0,1)
+ CodecEncoding.getCanonicalCodec(44) // (5,128,0,1)
+ };
+
+ public static BHSDCodec[] deltaUnsignedCodecs3 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(52), // (2,8,0,1)
+ CodecEncoding.getCanonicalCodec(54), // (2,16,0,1)
+ CodecEncoding.getCanonicalCodec(56), // (2,32,0,1)
+ CodecEncoding.getCanonicalCodec(58), // (2,64,0,1)
+ CodecEncoding.getCanonicalCodec(60), // (2,128,0,1)
+ CodecEncoding.getCanonicalCodec(62), // (2,192,0,1)
+ CodecEncoding.getCanonicalCodec(64), // (2,224,0,1)
+ CodecEncoding.getCanonicalCodec(66), // (2,240,0,1)
+ CodecEncoding.getCanonicalCodec(68) // (2,248,0,1)
+ };
+
+ public static BHSDCodec[] deltaUnsignedCodecs4 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(75), // (3,8,0,1)
+ CodecEncoding.getCanonicalCodec(77), // (3,16,0,1)
+ CodecEncoding.getCanonicalCodec(79), // (3,32,0,1)
+ CodecEncoding.getCanonicalCodec(81), // (3,64,0,1)
+ CodecEncoding.getCanonicalCodec(83), // (3,128,0,1)
+ CodecEncoding.getCanonicalCodec(85), // (3,192,0,1)
+ CodecEncoding.getCanonicalCodec(87), // (3,224,0,1)
+ CodecEncoding.getCanonicalCodec(89), // (3,240,0,1)
+ CodecEncoding.getCanonicalCodec(91) // (3,248,0,1)
+ };
+
+ public static BHSDCodec[] deltaUnsignedCodecs5 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(98), // (4,8,0,1)
+ CodecEncoding.getCanonicalCodec(100), // (4,16,0,1)
+ CodecEncoding.getCanonicalCodec(102), // (4,32,0,1)
+ CodecEncoding.getCanonicalCodec(104), // (4,64,0,1)
+ CodecEncoding.getCanonicalCodec(106), // (4,128,0,1)
+ CodecEncoding.getCanonicalCodec(108), // (4,192,0,1)
+ CodecEncoding.getCanonicalCodec(110), // (4,224,0,1)
+ CodecEncoding.getCanonicalCodec(112), // (4,240,0,1)
+ CodecEncoding.getCanonicalCodec(114) // (4,248,0,1)
+ };
+
+ // Families of codecs for bands containing positive and negative integers
+ // that do correlate well (i.e. delta encoding is used)
+
+ public static BHSDCodec[] deltaSignedCodecs1 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(4), // (1,256,1,1)
+ CodecEncoding.getCanonicalCodec(8), // (2,256,1,1)
+ CodecEncoding.getCanonicalCodec(12), // (3,256,1,1)
+ CodecEncoding.getCanonicalCodec(16) // (4,256,1,1)
+ };
+
+ public static BHSDCodec[] deltaSignedCodecs2 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(33), // (5,4,1,1)
+ CodecEncoding.getCanonicalCodec(36), // (5,16,1,1)
+ CodecEncoding.getCanonicalCodec(39), // (5,32,1,1)
+ CodecEncoding.getCanonicalCodec(42), // (5,64,1,1)
+ CodecEncoding.getCanonicalCodec(45) // (5,128,1,1)
+ };
+
+ public static BHSDCodec[] deltaSignedCodecs3 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(53), // (2,8,1,1)
+ CodecEncoding.getCanonicalCodec(55), // (2,16,1,1)
+ CodecEncoding.getCanonicalCodec(57), // (2,32,1,1)
+ CodecEncoding.getCanonicalCodec(59), // (2,64,1,1)
+ CodecEncoding.getCanonicalCodec(61), // (2,128,1,1)
+ CodecEncoding.getCanonicalCodec(63), // (2,192,1,1)
+ CodecEncoding.getCanonicalCodec(65), // (2,224,1,1)
+ CodecEncoding.getCanonicalCodec(67), // (2,240,1,1)
+ CodecEncoding.getCanonicalCodec(69) // (2,248,1,1)
+ };
+
+ public static BHSDCodec[] deltaSignedCodecs4 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(76), // (3,8,1,1)
+ CodecEncoding.getCanonicalCodec(78), // (3,16,1,1)
+ CodecEncoding.getCanonicalCodec(80), // (3,32,1,1)
+ CodecEncoding.getCanonicalCodec(82), // (3,64,1,1)
+ CodecEncoding.getCanonicalCodec(84), // (3,128,1,1)
+ CodecEncoding.getCanonicalCodec(86), // (3,192,1,1)
+ CodecEncoding.getCanonicalCodec(88), // (3,224,1,1)
+ CodecEncoding.getCanonicalCodec(90), // (3,240,1,1)
+ CodecEncoding.getCanonicalCodec(92) // (3,248,1,1)
+ };
+
+ public static BHSDCodec[] deltaSignedCodecs5 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(99), // (4,8,1,1)
+ CodecEncoding.getCanonicalCodec(101), // (4,16,1,1)
+ CodecEncoding.getCanonicalCodec(103), // (4,32,1,1)
+ CodecEncoding.getCanonicalCodec(105), // (4,64,1,1)
+ CodecEncoding.getCanonicalCodec(107), // (4,128,1,1)
+ CodecEncoding.getCanonicalCodec(109), // (4,192,1,1)
+ CodecEncoding.getCanonicalCodec(111), // (4,224,1,1)
+ CodecEncoding.getCanonicalCodec(113), // (4,240,1,1)
+ CodecEncoding.getCanonicalCodec(115) // (4,248,1,1)
+ };
+
+ public static BHSDCodec[] deltaDoubleSignedCodecs1 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(34), // (5,4,2,1)
+ CodecEncoding.getCanonicalCodec(37), // (5,16,2,1)
+ CodecEncoding.getCanonicalCodec(40), // (5,32,2,1)
+ CodecEncoding.getCanonicalCodec(43), // (5,64,2,1)
+ CodecEncoding.getCanonicalCodec(46) // (5,128,2,1)
+ };
+
+ // Families of codecs for bands containing positive and negative values that
+ // do not correlate well (i.e. delta encoding is not used)
+
+ public static BHSDCodec[] nonDeltaSignedCodecs1 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(2), // (1,256,1)
+ CodecEncoding.getCanonicalCodec(6), // (2,256,1)
+ CodecEncoding.getCanonicalCodec(10), // (3,256,1)
+ CodecEncoding.getCanonicalCodec(14) // (4,256,1)
+ };
+
+ public static BHSDCodec[] nonDeltaSignedCodecs2 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(18), // (5,4,1)
+ CodecEncoding.getCanonicalCodec(21), // (5,16,1)
+ CodecEncoding.getCanonicalCodec(24), // (5,32,1)
+ CodecEncoding.getCanonicalCodec(27), // (5,64,1)
+ CodecEncoding.getCanonicalCodec(30) // (5,128,1)
+ };
+
+ public static BHSDCodec[] nonDeltaDoubleSignedCodecs1 = new BHSDCodec[] {
+ CodecEncoding.getCanonicalCodec(19), // (5,4,2)
+ CodecEncoding.getCanonicalCodec(22), // (5,16,2)
+ CodecEncoding.getCanonicalCodec(25), // (5,32,2)
+ CodecEncoding.getCanonicalCodec(28), // (5,64,2)
+ CodecEncoding.getCanonicalCodec(31) // (5,128,2)
+ };
+
+}
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java Fri Jun 12 08:35:08 2009
@@ -85,6 +85,8 @@
*/
public static final BHSDCodec UNSIGNED5 = new BHSDCodec(5, 64);
+ public int lastBandLength;
+
/**
* Decode a sequence of bytes from the given input stream, returning the
* value as a long. Note that this method can only be applied for non-delta
@@ -99,7 +101,7 @@
* @throws Pack200Exception
* if the encoding is a delta encoding
*/
- public abstract long decode(InputStream in) throws IOException,
+ public abstract int decode(InputStream in) throws IOException,
Pack200Exception;
/**
@@ -112,7 +114,7 @@
* @return the encoded bytes
* @throws Pack200Exception
*/
- public abstract byte[] encode(long value, long last)
+ public abstract byte[] encode(int value, int last)
throws Pack200Exception;
/**
@@ -124,7 +126,7 @@
* @return the encoded bytes
* @throws Pack200Exception
*/
- public abstract byte[] encode(long value) throws Pack200Exception;
+ public abstract byte[] encode(int value) throws Pack200Exception;
/**
* Decode a sequence of bytes from the given input stream, returning the
@@ -154,7 +156,7 @@
* if there is a problem decoding the value or that the value is
* invalid
*/
- public abstract long decode(InputStream in, long last) throws IOException,
+ public abstract int decode(InputStream in, long last) throws IOException,
Pack200Exception;
/**
@@ -168,36 +170,6 @@
* the number of values to decode
* @param in
* the input stream to read from
- * @return an array of long values corresponding to values
- * decoded
- * @throws IOException
- * if there is a problem reading from the underlying input
- * stream
- * @throws Pack200Exception
- * if there is a problem decoding the value or that the value is
- * invalid
- */
- public long[] decode(int n, InputStream in) throws IOException,
- Pack200Exception {
- long result[] = new long[n];
- long last = 0;
- for (int i = 0; i < n; i++) {
- result[i] = last = decode(in, last);
- }
- return result;
- }
-
- /**
- * Decodes a sequence of n values from in.
- * This should probably be used in most cases, since some codecs (such as
- *
- * @{link PopCodec}) only work when the number of values to be read is
- * known.
- *
- * @param n
- * the number of values to decode
- * @param in
- * the input stream to read from
* @return an array of int values corresponding to values
* decoded
* @throws IOException
@@ -209,38 +181,10 @@
*/
public int[] decodeInts(int n, InputStream in) throws IOException,
Pack200Exception {
+ lastBandLength = 0;
int result[] = new int[n];
int last = 0;
for (int i = 0; i < n; i++) {
- result[i] = last = (int) decode(in, last);
- }
- return result;
- }
-
- /**
- * Decodes a sequence of n values from in.
- *
- * @param n
- * the number of values to decode
- * @param in
- * the input stream to read from
- * @param firstValue
- * the first value in the band if it has already been read
- * @return an array of long values corresponding to values
- * decoded, with firstValue as the first value in the array.
- * @throws IOException
- * if there is a problem reading from the underlying input
- * stream
- * @throws Pack200Exception
- * if there is a problem decoding the value or that the value is
- * invalid
- */
- public long[] decode(int n, InputStream in, long firstValue)
- throws IOException, Pack200Exception {
- long result[] = new long[n + 1];
- result[0] = firstValue;
- long last = firstValue;
- for (int i = 1; i < n + 1; i++) {
result[i] = last = decode(in, last);
}
return result;
@@ -270,7 +214,7 @@
result[0] = firstValue;
int last = firstValue;
for (int i = 1; i < n + 1; i++) {
- result[i] = last = (int) decode(in, last);
+ result[i] = last = decode(in, last);
}
return result;
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java Fri Jun 12 08:35:08 2009
@@ -34,7 +34,7 @@
* one of the standard encodings. The following values are defined in the
* Pack200 specification, and this array cannot be changed.
*/
- private static final Codec[] canonicalCodec = { null,
+ private static final BHSDCodec[] canonicalCodec = { null,
new BHSDCodec(1, 256), new BHSDCodec(1, 256, 1),
new BHSDCodec(1, 256, 0, 1), new BHSDCodec(1, 256, 1, 1),
new BHSDCodec(2, 256), new BHSDCodec(2, 256, 1),
@@ -292,7 +292,7 @@
int fDef = favouredCodec.equals(defaultForBand) ? 1 : 0;
int uDef = unfavouredCodec.equals(defaultForBand) ? 1 : 0;
int tDefL = 0;
- long[] favoured = populationCodec.getFavoured();
+ int[] favoured = populationCodec.getFavoured();
if(favoured != null) {
int k = favoured.length;
if(tokenCodec == Codec.BYTE1) {
@@ -334,4 +334,8 @@
return null;
}
+
+ public static BHSDCodec getCanonicalCodec(int i) {
+ return canonicalCodec[i];
+ }
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java Fri Jun 12 08:35:08 2009
@@ -93,9 +93,9 @@
writeCpClass(out);
writeCpSignature(out);
writeCpDescr(out);
- writeCpMethodOrField(cp_Field, out);
- writeCpMethodOrField(cp_Method, out);
- writeCpMethodOrField(cp_Imethod, out);
+ writeCpMethodOrField(cp_Field, out, "cp_Field");
+ writeCpMethodOrField(cp_Method, out, "cp_Method");
+ writeCpMethodOrField(cp_Imethod, out, "cp_Imethod");
}
private void writeCpUtf8(OutputStream out) throws IOException,
@@ -175,7 +175,7 @@
cpInt[i] = integer.getInt();
i++;
}
- out.write(encodeBandInt("cpInt", cpInt, Codec.UDELTA5));
+ out.write(encodeBandInt("cp_Int", cpInt, Codec.UDELTA5));
}
private void writeCpFloat(OutputStream out) throws IOException,
@@ -187,7 +187,7 @@
cpFloat[i] = Float.floatToIntBits(fl.getFloat());
i++;
}
- out.write(encodeBandInt("cpFloat", cpFloat, Codec.UDELTA5));
+ out.write(encodeBandInt("cp_Float", cpFloat, Codec.UDELTA5));
}
private void writeCpLong(OutputStream out) throws IOException,
@@ -278,11 +278,11 @@
cpDescrType[i] = nameAndType.getTypeIndex();
i++;
}
- out.write(encodeBandInt("cpDescrName", cpDescrName, Codec.DELTA5));
- out.write(encodeBandInt("cpDescrType", cpDescrType, Codec.UDELTA5));
+ out.write(encodeBandInt("cp_Descr_Name", cpDescrName, Codec.DELTA5));
+ out.write(encodeBandInt("cp_Descr_Type", cpDescrType, Codec.UDELTA5));
}
- private void writeCpMethodOrField(Set cp, OutputStream out)
+ private void writeCpMethodOrField(Set cp, OutputStream out, String name)
throws IOException, Pack200Exception {
int[] cp_methodOrField_class = new int[cp.size()];
int[] cp_methodOrField_desc = new int[cp.size()];
@@ -293,9 +293,9 @@
cp_methodOrField_desc[i] = mOrF.getDescIndex();
i++;
}
- out.write(encodeBandInt("cp_methodOrField_class",
+ out.write(encodeBandInt(name + "_class",
cp_methodOrField_class, Codec.DELTA5));
- out.write(encodeBandInt("cp_methodOrField_desc", cp_methodOrField_desc,
+ out.write(encodeBandInt(name + "_desc", cp_methodOrField_desc,
Codec.UDELTA5));
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java Fri Jun 12 08:35:08 2009
@@ -104,7 +104,7 @@
int index = 0;
for (int i = 0; i < bytes.length; i++) {
for (int j = 0; j < bytes[i].length; j++) {
- band[index++] = bytes[i][j];
+ band[index++] = bytes[i][j] & 0xFF;
}
}
return band;
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java Fri Jun 12 08:35:08 2009
@@ -22,7 +22,7 @@
/**
* A PopulationCodec is a Codec that is well suited to encoding data that shows
- * statistical or repetetive patterns, containign for example a few numbers
+ * statistical or repetitive patterns, containing for example a few numbers
* which are repeated a lot throughout the set, but not necessarily
* sequentially.
*/
@@ -32,12 +32,12 @@
private Codec tokenCodec;
private final Codec unvafouredCodec;
private int l;
- private long[] favoured;
+ private int[] favoured;
- public PopulationCodec(Codec favouredCodec, Codec tableCodec,
+ public PopulationCodec(Codec favouredCodec, Codec tokenCodec,
Codec unvafouredCodec) {
this.favouredCodec = favouredCodec;
- this.tokenCodec = tableCodec;
+ this.tokenCodec = tokenCodec;
this.unvafouredCodec = unvafouredCodec;
}
@@ -49,26 +49,27 @@
this.unvafouredCodec = unvafouredCodec;
}
- public long decode(InputStream in) throws IOException, Pack200Exception {
+ public int decode(InputStream in) throws IOException, Pack200Exception {
throw new Pack200Exception(
"Population encoding does not work unless the number of elements are known");
}
- public long decode(InputStream in, long last) throws IOException,
+ public int decode(InputStream in, long last) throws IOException,
Pack200Exception {
throw new Pack200Exception(
"Population encoding does not work unless the number of elements are known");
}
- public long[] decode(int n, InputStream in) throws IOException,
+ public int[] decodeInts(int n, InputStream in) throws IOException,
Pack200Exception {
- favoured = new long[n]; // there must be <= n values, but probably a lot
+ lastBandLength = 0;
+ favoured = new int[n]; // there must be <= n values, but probably a lot
// less
- long result[];
+ int result[];
// read table of favorites first
- long smallest = Long.MAX_VALUE;
- long last = 0;
- long value = 0;
+ int smallest = Integer.MAX_VALUE;
+ int last = 0;
+ int value = 0;
int k = -1;
while (true) {
value = favouredCodec.decode(in, last);
@@ -83,6 +84,7 @@
}
last = value;
}
+ lastBandLength += k;
// if tokenCodec needs to be derived from the T, L and K values
if (tokenCodec == null) {
if (k < 256) {
@@ -102,12 +104,14 @@
}
}
// read favorites
- result = tokenCodec.decode(n, in);
+ lastBandLength += n;
+ result = tokenCodec.decodeInts(n, in);
// read unfavorites
last = 0;
for (int i = 0; i < n; i++) {
- int index = (int) result[i];
+ int index = result[i];
if (index == 0) {
+ lastBandLength++;
result[i] = last = unvafouredCodec.decode(in, last);
} else {
result[i] = favoured[index - 1];
@@ -116,17 +120,7 @@
return result;
}
- public int[] decodeInts(int n, InputStream in) throws IOException,
- Pack200Exception {
- long[] result = decode(n, in);
- int[] intRes = new int[result.length];
- for (int i = 0; i < intRes.length; i++) {
- intRes[i] = (int) result[i];
- }
- return intRes;
- }
-
- public long[] getFavoured() {
+ public int[] getFavoured() {
return favoured;
}
@@ -138,14 +132,23 @@
return unvafouredCodec;
}
- public byte[] encode(long value, long last) throws Pack200Exception {
- // TODO Auto-generated method stub
- return null;
+ public byte[] encode(int value, int last) throws Pack200Exception {
+ throw new Pack200Exception(
+ "Population encoding does not work unless the number of elements are known");
}
- public byte[] encode(long value) throws Pack200Exception {
- // TODO Auto-generated method stub
- return null;
+ public byte[] encode(int value) throws Pack200Exception {
+ throw new Pack200Exception(
+ "Population encoding does not work unless the number of elements are known");
+ }
+
+ public byte[] encode(int[] favoured, int[] tokens, int[] unfavoured) throws Pack200Exception {
+ byte[] favouredEncoded = favouredCodec.encode(favoured);
+ byte[] tokensEncoded = tokenCodec.encode(tokens);
+ byte[] unfavouredEncoded = unvafouredCodec.encode(unfavoured);
+ byte[] band = new byte[favouredEncoded.length + tokensEncoded.length + unfavouredEncoded.length];
+
+ return band;
}
public Codec getTokenCodec() {
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java Fri Jun 12 08:35:08 2009
@@ -31,7 +31,7 @@
private int k;
private final Codec aCodec;
private final Codec bCodec;
- private long last;
+ private int last;
public RunCodec(int k, Codec aCodec, Codec bCodec) throws Pack200Exception {
if (k <= 0)
@@ -44,14 +44,14 @@
this.bCodec = bCodec;
}
- public long decode(InputStream in) throws IOException, Pack200Exception {
+ public int decode(InputStream in) throws IOException, Pack200Exception {
return decode(in, this.last);
}
- public long decode(InputStream in, long last) throws IOException,
+ public int decode(InputStream in, long last) throws IOException,
Pack200Exception {
if (--k >= 0) {
- long value = aCodec.decode(in, this.last);
+ int value = aCodec.decode(in, this.last);
this.last = (k == 0 ? 0 : value);
return normalise(aCodec, value);
} else {
@@ -60,7 +60,7 @@
}
}
- private long normalise(Codec codecUsed, long value) {
+ private int normalise(Codec codecUsed, int value) {
if (codecUsed instanceof BHSDCodec && ((BHSDCodec) codecUsed).isDelta()) {
BHSDCodec bhsd = (BHSDCodec) codecUsed;
long cardinality = bhsd.cardinality();
@@ -83,6 +83,7 @@
normalise(bValues, bCodec);
System.arraycopy(aValues, 0, band, 0, k);
System.arraycopy(bValues, 0, band, k, n - k);
+ lastBandLength = aCodec.lastBandLength + bCodec.lastBandLength;
return band;
}
@@ -100,7 +101,7 @@
}
} else if (codecUsed instanceof PopulationCodec) {
PopulationCodec popCodec = (PopulationCodec) codecUsed;
- long[] favoured = (long[]) popCodec.getFavoured().clone();
+ int[] favoured = (int[]) popCodec.getFavoured().clone();
Arrays.sort(favoured);
for (int i = 0; i < band.length; i++) {
boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1;
@@ -126,12 +127,12 @@
+ "]";
}
- public byte[] encode(long value, long last) throws Pack200Exception {
+ public byte[] encode(int value, int last) throws Pack200Exception {
// TODO Auto-generated method stub
return null;
}
- public byte[] encode(long value) throws Pack200Exception {
+ public byte[] encode(int value) throws Pack200Exception {
// TODO Auto-generated method stub
return null;
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java Fri Jun 12 08:35:08 2009
@@ -16,6 +16,7 @@
*/
package org.apache.harmony.pack200;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -70,13 +71,19 @@
bcBands.finaliseBands();
fileBands.finaliseBands();
+ // Temporary fix because we have to encode the other bands before
+ // segmentHeader, but probably not very good performance
+ ByteArrayOutputStream tempStream = new ByteArrayOutputStream();
+
+ cpBands.pack(tempStream);
+ attributeDefinitionBands.pack(tempStream);
+ icBands.pack(tempStream);
+ classBands.pack(tempStream);
+ bcBands.pack(tempStream);
+ fileBands.pack(tempStream);
+
segmentHeader.pack(out);
- cpBands.pack(out);
- attributeDefinitionBands.pack(out);
- icBands.pack(out);
- classBands.pack(out);
- bcBands.pack(out);
- fileBands.pack(out);
+ tempStream.writeTo(out);
}
private void processClasses(List classes) {
@@ -166,7 +173,7 @@
public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3,
Object[] arg4) {
- // TODO Auto-generated method stub
+ // TODO: Java 6 - implement support for this
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java Fri Jun 12 08:35:08 2009
@@ -108,20 +108,14 @@
// First element should not be discarded
band = codec.decodeInts(count - 1, in, first);
}
- if (codecUsed instanceof BHSDCodec && ((BHSDCodec) codecUsed).isDelta()) {
- BHSDCodec bhsd = (BHSDCodec) codecUsed;
- long cardinality = bhsd.cardinality();
- for (int i = 0; i < band.length; i++) {
- while (band[i] > bhsd.largest()) {
- band[i] -= cardinality;
- }
- while (band[i] < bhsd.smallest()) {
- band[i] += cardinality;
- }
- }
- } else if (codecUsed instanceof PopulationCodec) {
+ // Useful for debugging -E options:
+ //if(!codecUsed.equals(codec)) {
+ // int bytes = codecUsed.lastBandLength;
+ // System.out.println(count + " " + name + " encoded with " + codecUsed + " " + bytes);
+ //}
+ if (codecUsed instanceof PopulationCodec) {
PopulationCodec popCodec = (PopulationCodec) codecUsed;
- long[] favoured = (long[]) popCodec.getFavoured().clone();
+ int[] favoured = (int[]) popCodec.getFavoured().clone();
Arrays.sort(favoured);
for (int i = 0; i < band.length; i++) {
boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1;
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java Fri Jun 12 08:35:08 2009
@@ -103,16 +103,16 @@
public void read(InputStream in) throws IOException, Pack200Exception,
Error, Pack200Exception {
- long word[] = decodeScalar("archive_magic_word", in, Codec.BYTE1,
+ int word[] = decodeScalar("archive_magic_word", in, Codec.BYTE1,
magic.length);
for (int m = 0; m < magic.length; m++)
if (word[m] != magic[m])
throw new Error("Bad header");
- setArchiveMinorVersion((int) decodeScalar("archive_minver", in,
+ setArchiveMinorVersion(decodeScalar("archive_minver", in,
Codec.UNSIGNED5));
- setArchiveMajorVersion((int) decodeScalar("archive_majver", in,
+ setArchiveMajorVersion(decodeScalar("archive_majver", in,
Codec.UNSIGNED5));
- options = new SegmentOptions((int) decodeScalar("archive_options", in,
+ options = new SegmentOptions(decodeScalar("archive_options", in,
Codec.UNSIGNED5));
parseArchiveFileCounts(in);
parseArchiveSpecialCounts(in);
@@ -290,7 +290,7 @@
Codec.UNSIGNED5));
setArchiveModtime(decodeScalar("archive_modtime", in,
Codec.UNSIGNED5));
- numberOfFiles = (int) decodeScalar("file_count", in,
+ numberOfFiles = decodeScalar("file_count", in,
Codec.UNSIGNED5);
}
}
@@ -298,7 +298,7 @@
private void parseArchiveSpecialCounts(InputStream in) throws IOException,
Pack200Exception {
if (getOptions().hasSpecialFormats()) {
- bandHeadersSize = (int) decodeScalar("band_headers_size", in,
+ bandHeadersSize = decodeScalar("band_headers_size", in,
Codec.UNSIGNED5);
setAttributeDefinitionCount(decodeScalar("attr_definition_count",
in, Codec.UNSIGNED5));
@@ -307,37 +307,37 @@
private void parseClassCounts(InputStream in) throws IOException,
Pack200Exception {
- innerClassCount = (int) decodeScalar("ic_count", in, Codec.UNSIGNED5);
- defaultClassMinorVersion = (int) decodeScalar("default_class_minver",
+ innerClassCount = decodeScalar("ic_count", in, Codec.UNSIGNED5);
+ defaultClassMinorVersion = decodeScalar("default_class_minver",
in, Codec.UNSIGNED5);
- defaultClassMajorVersion = (int) decodeScalar("default_class_majver",
+ defaultClassMajorVersion = decodeScalar("default_class_majver",
in, Codec.UNSIGNED5);
- classCount = (int) decodeScalar("class_count", in, Codec.UNSIGNED5);
+ classCount = decodeScalar("class_count", in, Codec.UNSIGNED5);
}
private void parseCpCounts(InputStream in) throws IOException,
Pack200Exception {
- cpUTF8Count = (int) decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5);
+ cpUTF8Count = decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5);
if (getOptions().hasCPNumberCounts()) {
- cpIntCount = (int) decodeScalar("cp_Int_count", in, Codec.UNSIGNED5);
- cpFloatCount = (int) decodeScalar("cp_Float_count", in,
+ cpIntCount = decodeScalar("cp_Int_count", in, Codec.UNSIGNED5);
+ cpFloatCount = decodeScalar("cp_Float_count", in,
Codec.UNSIGNED5);
- cpLongCount = (int) decodeScalar("cp_Long_count", in,
+ cpLongCount = decodeScalar("cp_Long_count", in,
Codec.UNSIGNED5);
- cpDoubleCount = (int) decodeScalar("cp_Double_count", in,
+ cpDoubleCount = decodeScalar("cp_Double_count", in,
Codec.UNSIGNED5);
}
- cpStringCount = (int) decodeScalar("cp_String_count", in,
+ cpStringCount = decodeScalar("cp_String_count", in,
Codec.UNSIGNED5);
- cpClassCount = (int) decodeScalar("cp_Class_count", in, Codec.UNSIGNED5);
- cpSignatureCount = (int) decodeScalar("cp_Signature_count", in,
+ cpClassCount = decodeScalar("cp_Class_count", in, Codec.UNSIGNED5);
+ cpSignatureCount = decodeScalar("cp_Signature_count", in,
Codec.UNSIGNED5);
- cpDescriptorCount = (int) decodeScalar("cp_Descr_count", in,
+ cpDescriptorCount = decodeScalar("cp_Descr_count", in,
Codec.UNSIGNED5);
- cpFieldCount = (int) decodeScalar("cp_Field_count", in, Codec.UNSIGNED5);
- cpMethodCount = (int) decodeScalar("cp_Method_count", in,
+ cpFieldCount = decodeScalar("cp_Field_count", in, Codec.UNSIGNED5);
+ cpMethodCount = decodeScalar("cp_Method_count", in,
Codec.UNSIGNED5);
- cpIMethodCount = (int) decodeScalar("cp_Imethod_count", in,
+ cpIMethodCount = decodeScalar("cp_Imethod_count", in,
Codec.UNSIGNED5);
}
@@ -360,11 +360,11 @@
* if there is a problem decoding the value or that the value is
* invalid
*/
- private long[] decodeScalar(String name, InputStream in, BHSDCodec codec,
+ private int[] decodeScalar(String name, InputStream in, BHSDCodec codec,
int n) throws IOException, Pack200Exception {
segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " (" + n
+ ")");
- return codec.decode(n, in);
+ return codec.decodeInts(n, in);
}
/**
@@ -386,9 +386,9 @@
* if there is a problem decoding the value or that the value is
* invalid
*/
- private long decodeScalar(String name, InputStream in, BHSDCodec codec)
+ private int decodeScalar(String name, InputStream in, BHSDCodec codec)
throws IOException, Pack200Exception {
- long ret = codec.decode(in);
+ int ret = codec.decode(in);
segment
.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " as "
+ ret);
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java Fri Jun 12 08:35:08 2009
@@ -42,9 +42,13 @@
// range of the codec
long largest = codec.largest();
long smallest = codec.isSigned() ? codec.smallest() : 0;
+ if(smallest < Integer.MIN_VALUE) smallest = Integer.MIN_VALUE;
long difference = (largest - smallest) / 4;
for (long j = smallest; j <= largest; j += difference) {
- byte[] encoded = codec.encode(j, 0);
+ if(j > Integer.MAX_VALUE) {
+ break;
+ }
+ byte[] encoded = codec.encode((int)j, 0);
long decoded = 0;
try {
decoded = codec.decode(
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java Fri Jun 12 08:35:08 2009
@@ -23,6 +23,7 @@
import junit.framework.TestCase;
import org.apache.harmony.pack200.BHSDCodec;
+import org.apache.harmony.pack200.CanonicalCodecFamilies;
import org.apache.harmony.pack200.Codec;
import org.apache.harmony.pack200.Pack200Exception;
import org.apache.harmony.pack200.RunCodec;
@@ -203,8 +204,6 @@
(byte) 255, (byte) 191 }, 51130559, 0);
decode(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192,
(byte) 192, (byte) 192, 0 }, 51130560, 0);
- decode(Codec.UNSIGNED5, new byte[] { (byte) 255, (byte) 252,
- (byte) 252, (byte) 252, (byte) 252 }, 0xFFFFFFFFL, 0);
decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192 });
decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192 });
decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192,
@@ -212,6 +211,27 @@
decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192,
(byte) 192, (byte) 192 });
}
+ public void testCodecFamilies() {
+ checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1);
+ checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2);
+ checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3);
+ checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4);
+ checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5);
+ checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs1);
+ checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs2);
+ checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs3);
+ checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs4);
+ checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs5);
+ }
+
+ private void checkAscendingCardinalities(BHSDCodec[] family) {
+ for (int i = 1; i < family.length; i++) {
+ BHSDCodec previous = family[i-1];
+ BHSDCodec codec = family[i];
+ assertTrue(codec.largest() >= previous.largest());
+ assertTrue(codec.smallest() <= previous.smallest());
+ }
+ }
private void decodeFail(final Codec codec, final byte[] data)
throws IOException, Pack200Exception {
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java Fri Jun 12 08:35:08 2009
@@ -55,7 +55,7 @@
throws IOException, Pack200Exception {
InputStream in = new ByteArrayInputStream(data);
- long[] result = new PopulationCodec(codec, codec, codec).decode(
+ int[] result = new PopulationCodec(codec, codec, codec).decodeInts(
expectedResult.length, in);
assertEquals(expectedResult.length, result.length);
for (int i = 0; i < expectedResult.length; i++) {
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java?rev=784030&r1=784029&r2=784030&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java Fri Jun 12 08:35:08 2009
@@ -92,8 +92,8 @@
byte[] classThis = Codec.DELTA5.encode(1, 0);
byte[] classSuper = Codec.DELTA5.encode(2, 0);
byte[] classInterfaceCount = Codec.DELTA5.encode(2, 0);
- byte[] classInterfaceRef1 = encodeBandLong(
- new long[] { 3, 4 }, Codec.DELTA5);
+ byte[] classInterfaceRef1 = encodeBandInt(
+ new int[] { 3, 4 }, Codec.DELTA5);
byte[] classFieldCount = Codec.DELTA5.encode(0, 0);
byte[] classMethodCount = Codec.DELTA5.encode(0, 0);
byte[] classFlags = Codec.UNSIGNED5.encode(0, 0);
@@ -132,10 +132,10 @@
byte[] classInterfaceCount = Codec.DELTA5.encode(0, 0);
byte[] classFieldCount = Codec.DELTA5.encode(0, 0);
byte[] classMethodCount = Codec.DELTA5.encode(3, 0);
- byte[] methodDescr = encodeBandLong(new long[] { 0, 1, 2 },
+ byte[] methodDescr = encodeBandInt(new int[] { 0, 1, 2 },
Codec.MDELTA5);
- byte[] methodFlagsLo = encodeBandLong(
- new long[] { 0, 0, 0 }, Codec.UNSIGNED5);
+ byte[] methodFlagsLo = encodeBandInt(
+ new int[] { 0, 0, 0 }, Codec.UNSIGNED5);
byte[] classFlags = Codec.UNSIGNED5.encode(0, 0);
byte[][] allArrays = new byte[][] { classThis, classSuper,
classInterfaceCount, classFieldCount, classMethodCount,
@@ -166,7 +166,7 @@
cpDescriptor = null;
}
- public byte[] encodeBandLong(long[] data, BHSDCodec codec)
+ public byte[] encodeBandInt(int[] data, BHSDCodec codec)
throws IOException, Pack200Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < data.length; i++) {