1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.harmony.pack200;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.Arrays;
24
25 import org.apache.commons.compress.utils.ExactMath;
26
27
28
29
30
31 public class RunCodec extends Codec {
32
33 private int k;
34 private final Codec aCodec;
35 private final Codec bCodec;
36 private int last;
37
38 public RunCodec(final int k, final Codec aCodec, final Codec bCodec) throws Pack200Exception {
39 if (k <= 0) {
40 throw new Pack200Exception("Cannot have a RunCodec for a negative number of numbers");
41 }
42 if (aCodec == null || bCodec == null) {
43 throw new Pack200Exception("Must supply both codecs for a RunCodec");
44 }
45 this.k = k;
46 this.aCodec = aCodec;
47 this.bCodec = bCodec;
48 }
49
50 @Override
51 public int decode(final InputStream in) throws IOException, Pack200Exception {
52 return decode(in, this.last);
53 }
54
55 @Override
56 public int decode(final InputStream in, final long last) throws IOException, Pack200Exception {
57 if (--k >= 0) {
58 final int value = aCodec.decode(in, this.last);
59 this.last = k == 0 ? 0 : value;
60 return normalise(value, aCodec);
61 }
62 this.last = bCodec.decode(in, this.last);
63 return normalise(this.last, bCodec);
64 }
65
66 @Override
67 public int[] decodeInts(final int n, final InputStream in) throws IOException, Pack200Exception {
68 final int[] aValues = aCodec.decodeInts(k, in);
69 normalise(aValues, aCodec);
70 final int[] bValues = bCodec.decodeInts(n - k, in);
71 normalise(bValues, bCodec);
72 final int[] band = new int[check(n, in)];
73 System.arraycopy(aValues, 0, band, 0, k);
74 System.arraycopy(bValues, 0, band, k, n - k);
75 lastBandLength = aCodec.lastBandLength + bCodec.lastBandLength;
76 return band;
77 }
78
79 @Override
80 public byte[] encode(final int value) throws Pack200Exception {
81 throw new Pack200Exception("Must encode entire band at once with a RunCodec");
82 }
83
84 @Override
85 public byte[] encode(final int value, final int last) throws Pack200Exception {
86 throw new Pack200Exception("Must encode entire band at once with a RunCodec");
87 }
88
89 public Codec getACodec() {
90 return aCodec;
91 }
92
93 public Codec getBCodec() {
94 return bCodec;
95 }
96
97 public int getK() {
98 return k;
99 }
100
101 private int normalise(int value, final Codec codecUsed) {
102 if (codecUsed instanceof BHSDCodec) {
103 final BHSDCodec bhsd = (BHSDCodec) codecUsed;
104 if (bhsd.isDelta()) {
105 final long cardinality = bhsd.cardinality();
106 while (value > bhsd.largest()) {
107 value -= cardinality;
108 }
109 while (value < bhsd.smallest()) {
110 value = ExactMath.add(value, cardinality);
111 }
112 }
113 }
114 return value;
115 }
116
117 private void normalise(final int[] band, final Codec codecUsed) {
118 if (codecUsed instanceof BHSDCodec) {
119 final BHSDCodec bhsd = (BHSDCodec) codecUsed;
120 if (bhsd.isDelta()) {
121 final long cardinality = bhsd.cardinality();
122 for (int i = 0; i < band.length; i++) {
123 while (band[i] > bhsd.largest()) {
124 band[i] -= cardinality;
125 }
126 while (band[i] < bhsd.smallest()) {
127 band[i] = ExactMath.add(band[i], cardinality);
128 }
129 }
130 }
131 } else if (codecUsed instanceof PopulationCodec) {
132 final PopulationCodec popCodec = (PopulationCodec) codecUsed;
133 final int[] favoured = popCodec.getFavoured().clone();
134 Arrays.sort(favoured);
135 for (int i = 0; i < band.length; i++) {
136 final boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1;
137 final Codec theCodec = favouredValue ? popCodec.getFavouredCodec() : popCodec.getUnfavouredCodec();
138 if (theCodec instanceof BHSDCodec) {
139 final BHSDCodec bhsd = (BHSDCodec) theCodec;
140 if (bhsd.isDelta()) {
141 final long cardinality = bhsd.cardinality();
142 while (band[i] > bhsd.largest()) {
143 band[i] -= cardinality;
144 }
145 while (band[i] < bhsd.smallest()) {
146 band[i] = ExactMath.add(band[i], cardinality);
147 }
148 }
149 }
150 }
151 }
152 }
153
154 @Override
155 public String toString() {
156 return "RunCodec[k=" + k + ";aCodec=" + aCodec + "bCodec=" + bCodec + "]";
157 }
158 }