1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.unpack200;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.Arrays;
22
23 import org.apache.commons.compress.harmony.pack200.BHSDCodec;
24 import org.apache.commons.compress.harmony.pack200.Codec;
25 import org.apache.commons.compress.harmony.pack200.CodecEncoding;
26 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
27 import org.apache.commons.compress.harmony.pack200.PopulationCodec;
28 import org.apache.commons.compress.harmony.unpack200.bytecode.CPClass;
29 import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble;
30 import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef;
31 import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat;
32 import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger;
33 import org.apache.commons.compress.harmony.unpack200.bytecode.CPInterfaceMethodRef;
34 import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong;
35 import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef;
36 import org.apache.commons.compress.harmony.unpack200.bytecode.CPNameAndType;
37 import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
38 import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
39 import org.apache.commons.compress.utils.ExactMath;
40
41
42
43
44 public abstract class BandSet {
45
46 protected Segment segment;
47
48 protected SegmentHeader header;
49
50 public BandSet(final Segment segment) {
51 this.segment = segment;
52 this.header = segment.getSegmentHeader();
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66 public int[] decodeBandInt(final String name, final InputStream in, final BHSDCodec codec, final int count) throws IOException, Pack200Exception {
67 if (count < 0) {
68 throw new Pack200Exception("count < 0");
69 }
70
71
72
73
74 Codec codecUsed = codec;
75 if (codec.getB() == 1 || count == 0) {
76 return codec.decodeInts(count, in);
77 }
78 final int[] getFirst = codec.decodeInts(1, in);
79 if (getFirst.length == 0) {
80 return getFirst;
81 }
82 final int first = getFirst[0];
83 int[] band;
84 if (codec.isSigned() && first >= -256 && first <= -1) {
85
86 codecUsed = CodecEncoding.getCodec(-1 - first, header.getBandHeadersInputStream(), codec);
87 band = codecUsed.decodeInts(count, in);
88 } else if (!codec.isSigned() && first >= codec.getL() && first <= codec.getL() + 255) {
89
90 codecUsed = CodecEncoding.getCodec(first - codec.getL(), header.getBandHeadersInputStream(), codec);
91 band = codecUsed.decodeInts(count, in);
92 } else {
93
94 band = codec.decodeInts(count - 1, in, first);
95 }
96
97
98
99
100
101 if (codecUsed instanceof PopulationCodec) {
102 final PopulationCodec popCodec = (PopulationCodec) codecUsed;
103 final int[] favoured = popCodec.getFavoured().clone();
104 Arrays.sort(favoured);
105 for (int i = 0; i < band.length; i++) {
106 final boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1;
107 final Codec theCodec = favouredValue ? popCodec.getFavouredCodec() : popCodec.getUnfavouredCodec();
108 if (theCodec instanceof BHSDCodec && ((BHSDCodec) theCodec).isDelta()) {
109 final BHSDCodec bhsd = (BHSDCodec) theCodec;
110 final long cardinality = bhsd.cardinality();
111 while (band[i] > bhsd.largest()) {
112 band[i] -= cardinality;
113 }
114 while (band[i] < bhsd.smallest()) {
115 band[i] = ExactMath.add(band[i], cardinality);
116 }
117 }
118 }
119 }
120 return band;
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134 public int[][] decodeBandInt(final String name, final InputStream in, final BHSDCodec defaultCodec, final int[] counts)
135 throws IOException, Pack200Exception {
136 final int[][] result = new int[counts.length][];
137 int totalCount = 0;
138 for (final int count : counts) {
139 totalCount += count;
140 }
141 final int[] twoDResult = decodeBandInt(name, in, defaultCodec, totalCount);
142 int index = 0;
143 for (int i = 0; i < result.length; i++) {
144 if (counts[i] > twoDResult.length) {
145 throw new IOException("Counts value exceeds length of twoDResult");
146 }
147 result[i] = new int[counts[i]];
148 for (int j = 0; j < result[i].length; j++) {
149 result[i][j] = twoDResult[index];
150 index++;
151 }
152 }
153 return result;
154 }
155
156 protected String[] getReferences(final int[] ints, final String[] reference) {
157 final String[] result = new String[ints.length];
158 Arrays.setAll(result, i -> reference[ints[i]]);
159 return result;
160 }
161
162 protected String[][] getReferences(final int[][] ints, final String[] reference) {
163 final String[][] result = new String[ints.length][];
164 for (int i = 0; i < result.length; i++) {
165 result[i] = new String[ints[i].length];
166 for (int j = 0; j < result[i].length; j++) {
167 result[i][j] = reference[ints[i][j]];
168 }
169 }
170 return result;
171 }
172
173 public CPClass[] parseCPClassReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
174 throws IOException, Pack200Exception {
175 final int[] indices = decodeBandInt(name, in, codec, count);
176 final CPClass[] result = new CPClass[indices.length];
177 for (int i1 = 0; i1 < count; i1++) {
178 result[i1] = segment.getCpBands().cpClassValue(indices[i1]);
179 }
180 return result;
181 }
182
183 public CPNameAndType[] parseCPDescriptorReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
184 throws IOException, Pack200Exception {
185 final CpBands cpBands = segment.getCpBands();
186 final int[] indices = decodeBandInt(name, in, codec, count);
187 final CPNameAndType[] result = new CPNameAndType[indices.length];
188 for (int i1 = 0; i1 < count; i1++) {
189 final int index = indices[i1];
190 result[i1] = cpBands.cpNameAndTypeValue(index);
191 }
192 return result;
193 }
194
195 public CPDouble[] parseCPDoubleReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
196 throws IOException, Pack200Exception {
197 final int[] indices = decodeBandInt(name, in, codec, count);
198 final CPDouble[] result = new CPDouble[indices.length];
199 for (int i1 = 0; i1 < count; i1++) {
200 result[i1] = segment.getCpBands().cpDoubleValue(indices[i1]);
201 }
202 return result;
203 }
204
205 public CPFieldRef[] parseCPFieldRefReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
206 throws IOException, Pack200Exception {
207 final CpBands cpBands = segment.getCpBands();
208 final int[] indices = decodeBandInt(name, in, codec, count);
209 final CPFieldRef[] result = new CPFieldRef[indices.length];
210 for (int i1 = 0; i1 < count; i1++) {
211 final int index = indices[i1];
212 result[i1] = cpBands.cpFieldValue(index);
213 }
214 return result;
215 }
216
217 public CPFloat[] parseCPFloatReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
218 throws IOException, Pack200Exception {
219 final int[] indices = decodeBandInt(name, in, codec, count);
220 final CPFloat[] result = new CPFloat[indices.length];
221 for (int i1 = 0; i1 < count; i1++) {
222 result[i1] = segment.getCpBands().cpFloatValue(indices[i1]);
223 }
224 return result;
225 }
226
227 public CPInterfaceMethodRef[] parseCPInterfaceMethodRefReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
228 throws IOException, Pack200Exception {
229 final CpBands cpBands = segment.getCpBands();
230 final int[] indices = decodeBandInt(name, in, codec, count);
231 final CPInterfaceMethodRef[] result = new CPInterfaceMethodRef[indices.length];
232 for (int i1 = 0; i1 < count; i1++) {
233 result[i1] = cpBands.cpIMethodValue(indices[i1]);
234 }
235 return result;
236 }
237
238 public CPInteger[] parseCPIntReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
239 throws IOException, Pack200Exception {
240 final int[] reference = segment.getCpBands().getCpInt();
241 final int[] indices = decodeBandInt(name, in, codec, count);
242 final CPInteger[] result = new CPInteger[indices.length];
243 for (int i1 = 0; i1 < count; i1++) {
244 final int index = indices[i1];
245 if (index < 0 || index >= reference.length) {
246 throw new Pack200Exception("Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length);
247 }
248 result[i1] = segment.getCpBands().cpIntegerValue(index);
249 }
250 return result;
251 }
252
253 public CPLong[] parseCPLongReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
254 throws IOException, Pack200Exception {
255 final long[] reference = segment.getCpBands().getCpLong();
256 final int[] indices = decodeBandInt(name, in, codec, count);
257 final CPLong[] result = new CPLong[indices.length];
258 for (int i1 = 0; i1 < count; i1++) {
259 final int index = indices[i1];
260 if (index < 0 || index >= reference.length) {
261 throw new Pack200Exception("Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length);
262 }
263 result[i1] = segment.getCpBands().cpLongValue(index);
264 }
265 return result;
266 }
267
268 public CPMethodRef[] parseCPMethodRefReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
269 throws IOException, Pack200Exception {
270 final CpBands cpBands = segment.getCpBands();
271 final int[] indices = decodeBandInt(name, in, codec, count);
272 final CPMethodRef[] result = new CPMethodRef[indices.length];
273 for (int i1 = 0; i1 < count; i1++) {
274 result[i1] = cpBands.cpMethodValue(indices[i1]);
275 }
276 return result;
277 }
278
279 public CPUTF8[] parseCPSignatureReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
280 throws IOException, Pack200Exception {
281 final int[] indices = decodeBandInt(name, in, codec, count);
282 final CPUTF8[] result = new CPUTF8[indices.length];
283 for (int i1 = 0; i1 < count; i1++) {
284 result[i1] = segment.getCpBands().cpSignatureValue(indices[i1]);
285 }
286 return result;
287 }
288
289 protected CPUTF8[][] parseCPSignatureReferences(final String name, final InputStream in, final BHSDCodec codec, final int[] counts)
290 throws IOException, Pack200Exception {
291 int sum = 0;
292 for (int i = 0; i < counts.length; i++) {
293 sum += counts[i];
294 }
295 final int[] indices = decodeBandInt(name, in, codec, sum);
296 final CPUTF8[] result1 = new CPUTF8[sum];
297 for (int i1 = 0; i1 < sum; i1++) {
298 result1[i1] = segment.getCpBands().cpSignatureValue(indices[i1]);
299 }
300 int pos = 0;
301 final CPUTF8[][] result = new CPUTF8[counts.length][];
302 for (int i = 0; i < counts.length; i++) {
303 final int num = counts[i];
304 result[i] = new CPUTF8[num];
305 System.arraycopy(result1, pos, result[i], 0, num);
306 pos += num;
307 }
308 return result;
309 }
310
311 public CPString[] parseCPStringReferences(final String name, final InputStream in, final BHSDCodec codec, final int count)
312 throws IOException, Pack200Exception {
313 final int[] indices = decodeBandInt(name, in, codec, count);
314 final CPString[] result = new CPString[indices.length];
315 for (int i1 = 0; i1 < count; i1++) {
316 result[i1] = segment.getCpBands().cpStringValue(indices[i1]);
317 }
318 return result;
319 }
320
321 public CPUTF8[] parseCPUTF8References(final String name, final InputStream in, final BHSDCodec codec, final int count)
322 throws IOException, Pack200Exception {
323 final int[] indices = decodeBandInt(name, in, codec, count);
324 final CPUTF8[] result = new CPUTF8[indices.length];
325 for (int i1 = 0; i1 < count; i1++) {
326 final int index = indices[i1];
327 result[i1] = segment.getCpBands().cpUTF8Value(index);
328 }
329 return result;
330 }
331
332 public CPUTF8[][] parseCPUTF8References(final String name, final InputStream in, final BHSDCodec codec, final int[] counts)
333 throws IOException, Pack200Exception {
334 final CPUTF8[][] result = new CPUTF8[counts.length][];
335 int sum = 0;
336 for (int i = 0; i < counts.length; i++) {
337 result[i] = new CPUTF8[counts[i]];
338 sum += counts[i];
339 }
340 final CPUTF8[] result1 = new CPUTF8[sum];
341 final int[] indices = decodeBandInt(name, in, codec, sum);
342 for (int i1 = 0; i1 < sum; i1++) {
343 final int index = indices[i1];
344 result1[i1] = segment.getCpBands().cpUTF8Value(index);
345 }
346 int pos = 0;
347 for (int i = 0; i < counts.length; i++) {
348 final int num = counts[i];
349 result[i] = new CPUTF8[num];
350 System.arraycopy(result1, pos, result[i], 0, num);
351 pos += num;
352 }
353 return result;
354 }
355
356 public long[] parseFlags(final String name, final InputStream in, final int count, final BHSDCodec hiCodec, final BHSDCodec loCodec)
357 throws IOException, Pack200Exception {
358 return parseFlags(name, in, new int[] { count }, hiCodec, loCodec)[0];
359 }
360
361 public long[] parseFlags(final String name, final InputStream in, final int count, final BHSDCodec codec, final boolean hasHi)
362 throws IOException, Pack200Exception {
363 return parseFlags(name, in, new int[] { count }, hasHi ? codec : null, codec)[0];
364 }
365
366 public long[][] parseFlags(final String name, final InputStream in, final int[] counts, final BHSDCodec hiCodec, final BHSDCodec loCodec)
367 throws IOException, Pack200Exception {
368 final int count = counts.length;
369 if (count == 0) {
370 return new long[][] { {} };
371 }
372 int sum = 0;
373 final long[][] result = new long[count][];
374 for (int i = 0; i < count; i++) {
375 sum += counts[i];
376 }
377 int[] hi = null;
378 int[] lo;
379 if (hiCodec != null) {
380 hi = decodeBandInt(name, in, hiCodec, sum);
381 }
382 lo = decodeBandInt(name, in, loCodec, sum);
383
384 int index = 0;
385 for (int i = 0; i < count; i++) {
386 result[i] = new long[counts[i]];
387 for (int j = 0; j < result[i].length; j++) {
388 if (hi != null) {
389 result[i][j] = (long) hi[index] << 32 | lo[index] & 4294967295L;
390 } else {
391 result[i][j] = lo[index];
392 }
393 index++;
394 }
395 }
396 return result;
397 }
398
399 public long[][] parseFlags(final String name, final InputStream in, final int[] counts, final BHSDCodec codec, final boolean hasHi)
400 throws IOException, Pack200Exception {
401 return parseFlags(name, in, counts, hasHi ? codec : null, codec);
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 public String[] parseReferences(final String name, final InputStream in, final BHSDCodec codec, final int count, final String[] reference)
419 throws IOException, Pack200Exception {
420 return parseReferences(name, in, codec, new int[] { count }, reference)[0];
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 public String[][] parseReferences(final String name, final InputStream in, final BHSDCodec codec, final int[] counts, final String[] reference)
439 throws IOException, Pack200Exception {
440 final int count = counts.length;
441 if (count == 0) {
442 return new String[][] { {} };
443 }
444 int sum = 0;
445 for (int i = 0; i < count; i++) {
446 sum += counts[i];
447 }
448
449 final int[] indices = decodeBandInt(name, in, codec, sum);
450 final String[] result1 = new String[sum];
451 for (int i1 = 0; i1 < sum; i1++) {
452 final int index = indices[i1];
453 if (index < 0 || index >= reference.length) {
454 throw new Pack200Exception("Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length);
455 }
456 result1[i1] = reference[index];
457 }
458
459 final String[][] result = new String[count][];
460 int pos = 0;
461 for (int i = 0; i < count; i++) {
462 final int num = counts[i];
463 result[i] = new String[num];
464 System.arraycopy(result1, pos, result[i], 0, num);
465 pos += num;
466 }
467 return result;
468 }
469
470 public abstract void read(InputStream inputStream) throws IOException, Pack200Exception;
471
472 public abstract void unpack() throws IOException, Pack200Exception;
473
474 public void unpack(final InputStream in) throws IOException, Pack200Exception {
475 read(in);
476 unpack();
477 }
478
479 }