in modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java [380:547]
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 = integerListToArray(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);
}
}
}