001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021:
022: public class PopulationCodec extends Codec {
023: private Codec favouredCodec;
024: private Codec tokenCodec;
025: private Codec unvafouredCodec;
026: private int l;
027: private long[] favoured;
028:
029: public PopulationCodec(Codec favouredCodec, Codec tableCodec,
030: Codec unvafouredCodec) {
031: this .favouredCodec = favouredCodec;
032: this .tokenCodec = tableCodec;
033: this .unvafouredCodec = unvafouredCodec;
034: }
035:
036: public PopulationCodec(Codec favouredCodec, int l,
037: Codec unvafouredCodec) {
038: if (l >= 256 || l <= 0)
039: throw new IllegalArgumentException(
040: "L must be between 1..255");
041: this .favouredCodec = favouredCodec;
042: this .l = l;
043: this .unvafouredCodec = unvafouredCodec;
044: }
045:
046: public long decode(InputStream in) throws IOException,
047: Pack200Exception {
048: throw new Pack200Exception(
049: "Population encoding does not work unless the number of elements are known");
050: }
051:
052: public long decode(InputStream in, long last) throws IOException,
053: Pack200Exception {
054: throw new Pack200Exception(
055: "Population encoding does not work unless the number of elements are known");
056: }
057:
058: public long[] decode(int n, InputStream in) throws IOException,
059: Pack200Exception {
060: favoured = new long[n]; // there must be <= n values, but probably a lot less
061: long result[];
062: // read table of favorites first
063: long smallest = Long.MAX_VALUE;
064: long last = 0;
065: long value = 0; // TODO Are these sensible starting points?
066: int k = -1;
067: while (true) {
068: last = value;
069: value = favouredCodec.decode(in, last);
070: if (value == smallest || value == last)
071: break;
072: favoured[++k] = value;
073: if (Math.abs(smallest) > Math.abs(value)) {
074: smallest = value;
075: } else if (Math.abs(smallest) == Math.abs(value)) {
076: // ensure that -X and +X -> +X
077: smallest = Math.abs(smallest);
078: }
079: }
080: // if tokenCodec needs to be derived from the T, L and K values
081: if (tokenCodec == null) {
082: if (k < 256) {
083: tokenCodec = Codec.BYTE1;
084: } else {
085: // if k >= 256, b >= 2
086: int b = 1;
087: while (++b < 5 && tokenCodec == null) {
088: BHSDCodec codec = new BHSDCodec(b, 256 - l, 0);
089: if (codec.encodes(k))
090: tokenCodec = codec;
091: }
092: if (tokenCodec == null)
093: throw new Pack200Exception(
094: "Cannot calculate token codec from " + k
095: + " and " + l);
096: }
097: }
098: // read favorites
099: result = tokenCodec.decode(n, in);
100: // read unfavorites
101: last = 0;
102: for (int i = 0; i < n; i++) {
103: int index = (int) result[i];
104: if (index == 0) {
105: result[i] = last = unvafouredCodec.decode(in, last);
106: } else {
107: result[i] = favoured[index - 1];
108: }
109: }
110: return result;
111: }
112:
113: public long[] getFavoured() {
114: return favoured;
115: }
116:
117: public Codec getFavouredCodec() {
118: return favouredCodec;
119: }
120:
121: public Codec getUnvafouredCodec() {
122: return unvafouredCodec;
123: }
124: }
|