1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.pack200;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeSet;
29
30 import org.objectweb.asm.Type;
31
32
33
34
35 public class CpBands extends BandSet {
36
37
38 private final Set<String> defaultAttributeNames = new HashSet<>();
39
40 private final Set<CPUTF8> cp_Utf8 = new TreeSet<>();
41 private final Set<CPInt> cp_Int = new TreeSet<>();
42 private final Set<CPFloat> cp_Float = new TreeSet<>();
43 private final Set<CPLong> cp_Long = new TreeSet<>();
44 private final Set<CPDouble> cp_Double = new TreeSet<>();
45 private final Set<CPString> cp_String = new TreeSet<>();
46 private final Set<CPClass> cp_Class = new TreeSet<>();
47 private final Set<CPSignature> cp_Signature = new TreeSet<>();
48 private final Set<CPNameAndType> cp_Descr = new TreeSet<>();
49 private final Set<CPMethodOrField> cp_Field = new TreeSet<>();
50 private final Set<CPMethodOrField> cp_Method = new TreeSet<>();
51 private final Set<CPMethodOrField> cp_Imethod = new TreeSet<>();
52
53 private final Map<String, CPUTF8> stringsToCpUtf8 = new HashMap<>();
54 private final Map<String, CPNameAndType> stringsToCpNameAndType = new HashMap<>();
55 private final Map<String, CPClass> stringsToCpClass = new HashMap<>();
56 private final Map<String, CPSignature> stringsToCpSignature = new HashMap<>();
57 private final Map<String, CPMethodOrField> stringsToCpMethod = new HashMap<>();
58 private final Map<String, CPMethodOrField> stringsToCpField = new HashMap<>();
59 private final Map<String, CPMethodOrField> stringsToCpIMethod = new HashMap<>();
60
61 private final Map<Object, CPConstant<?>> objectsToCPConstant = new HashMap<>();
62
63 private final Segment segment;
64
65 public CpBands(final Segment segment, final int effort) {
66 super(effort, segment.getSegmentHeader());
67 this.segment = segment;
68 defaultAttributeNames.add("AnnotationDefault");
69 defaultAttributeNames.add("RuntimeVisibleAnnotations");
70 defaultAttributeNames.add("RuntimeInvisibleAnnotations");
71 defaultAttributeNames.add("RuntimeVisibleParameterAnnotations");
72 defaultAttributeNames.add("RuntimeInvisibleParameterAnnotations");
73 defaultAttributeNames.add("Code");
74 defaultAttributeNames.add("LineNumberTable");
75 defaultAttributeNames.add("LocalVariableTable");
76 defaultAttributeNames.add("LocalVariableTypeTable");
77 defaultAttributeNames.add("ConstantValue");
78 defaultAttributeNames.add("Deprecated");
79 defaultAttributeNames.add("EnclosingMethod");
80 defaultAttributeNames.add("Exceptions");
81 defaultAttributeNames.add("InnerClasses");
82 defaultAttributeNames.add("Signature");
83 defaultAttributeNames.add("SourceFile");
84 }
85
86 private void addCharacters(final List<Character> chars, final char[] charArray) {
87 for (final char element : charArray) {
88 chars.add(Character.valueOf(element));
89 }
90 }
91
92 public void addCPClass(final String className) {
93 getCPClass(className);
94 }
95
96 void addCPUtf8(final String utf8) {
97 getCPUtf8(utf8);
98 }
99
100 private void addIndices() {
101 for (final Set<? extends ConstantPoolEntry> set : Arrays.asList(cp_Utf8, cp_Int, cp_Float, cp_Long, cp_Double, cp_String, cp_Class, cp_Signature,
102 cp_Descr, cp_Field, cp_Method, cp_Imethod)) {
103 int j = 0;
104 for (final ConstantPoolEntry entry : set) {
105 entry.setIndex(j);
106 j++;
107 }
108 }
109 final Map<CPClass, Integer> classNameToIndex = new HashMap<>();
110 cp_Field.forEach(mOrF -> {
111 final CPClass cpClassName = mOrF.getClassName();
112 final Integer index = classNameToIndex.get(cpClassName);
113 if (index == null) {
114 classNameToIndex.put(cpClassName, Integer.valueOf(1));
115 mOrF.setIndexInClass(0);
116 } else {
117 final int theIndex = index.intValue();
118 mOrF.setIndexInClass(theIndex);
119 classNameToIndex.put(cpClassName, Integer.valueOf(theIndex + 1));
120 }
121 });
122 classNameToIndex.clear();
123 final Map<CPClass, Integer> classNameToConstructorIndex = new HashMap<>();
124 cp_Method.forEach(mOrF -> {
125 final CPClass cpClassName = mOrF.getClassName();
126 final Integer index = classNameToIndex.get(cpClassName);
127 if (index == null) {
128 classNameToIndex.put(cpClassName, Integer.valueOf(1));
129 mOrF.setIndexInClass(0);
130 } else {
131 final int theIndex = index.intValue();
132 mOrF.setIndexInClass(theIndex);
133 classNameToIndex.put(cpClassName, Integer.valueOf(theIndex + 1));
134 }
135 if (mOrF.getDesc().getName().equals("<init>")) {
136 final Integer constructorIndex = classNameToConstructorIndex.get(cpClassName);
137 if (constructorIndex == null) {
138 classNameToConstructorIndex.put(cpClassName, Integer.valueOf(1));
139 mOrF.setIndexInClassForConstructor(0);
140 } else {
141 final int theIndex = constructorIndex.intValue();
142 mOrF.setIndexInClassForConstructor(theIndex);
143 classNameToConstructorIndex.put(cpClassName, Integer.valueOf(theIndex + 1));
144 }
145 }
146 });
147 }
148
149 public boolean existsCpClass(final String className) {
150 return stringsToCpClass.containsKey(className);
151 }
152
153
154
155
156
157 public void finaliseBands() {
158 addCPUtf8("");
159 removeSignaturesFromCpUTF8();
160 addIndices();
161 segmentHeader.setCp_Utf8_count(cp_Utf8.size());
162 segmentHeader.setCp_Int_count(cp_Int.size());
163 segmentHeader.setCp_Float_count(cp_Float.size());
164 segmentHeader.setCp_Long_count(cp_Long.size());
165 segmentHeader.setCp_Double_count(cp_Double.size());
166 segmentHeader.setCp_String_count(cp_String.size());
167 segmentHeader.setCp_Class_count(cp_Class.size());
168 segmentHeader.setCp_Signature_count(cp_Signature.size());
169 segmentHeader.setCp_Descr_count(cp_Descr.size());
170 segmentHeader.setCp_Field_count(cp_Field.size());
171 segmentHeader.setCp_Method_count(cp_Method.size());
172 segmentHeader.setCp_Imethod_count(cp_Imethod.size());
173 }
174
175 public CPConstant<?> getConstant(final Object value) {
176 CPConstant<?> constant = objectsToCPConstant.get(value);
177 if (constant == null) {
178 if (value instanceof Integer) {
179 constant = new CPInt(((Integer) value).intValue());
180 cp_Int.add((CPInt) constant);
181 } else if (value instanceof Long) {
182 constant = new CPLong(((Long) value).longValue());
183 cp_Long.add((CPLong) constant);
184 } else if (value instanceof Float) {
185 constant = new CPFloat(((Float) value).floatValue());
186 cp_Float.add((CPFloat) constant);
187 } else if (value instanceof Double) {
188 constant = new CPDouble(((Double) value).doubleValue());
189 cp_Double.add((CPDouble) constant);
190 } else if (value instanceof String) {
191 constant = new CPString(getCPUtf8((String) value));
192 cp_String.add((CPString) constant);
193 } else if (value instanceof Type) {
194 String className = ((Type) value).getClassName();
195 if (className.endsWith("[]")) {
196 className = "[L" + className.substring(0, className.length() - 2);
197 while (className.endsWith("[]")) {
198 className = "[" + className.substring(0, className.length() - 2);
199 }
200 className += ";";
201 }
202 constant = getCPClass(className);
203 }
204 objectsToCPConstant.put(value, constant);
205 }
206 return constant;
207 }
208
209 public CPClass getCPClass(String className) {
210 if (className == null) {
211 return null;
212 }
213 className = className.replace('.', '/');
214 CPClass cpClass = stringsToCpClass.get(className);
215 if (cpClass == null) {
216 final CPUTF8 cpUtf8 = getCPUtf8(className);
217 cpClass = new CPClass(cpUtf8);
218 cp_Class.add(cpClass);
219 stringsToCpClass.put(className, cpClass);
220 }
221 if (cpClass.isInnerClass()) {
222 segment.getClassBands().currentClassReferencesInnerClass(cpClass);
223 }
224 return cpClass;
225 }
226
227 public CPMethodOrField getCPField(final CPClass cpClass, final String name, final String desc) {
228 final String key = cpClass.toString() + ":" + name + ":" + desc;
229 CPMethodOrField cpF = stringsToCpField.get(key);
230 if (cpF == null) {
231 final CPNameAndType nAndT = getCPNameAndType(name, desc);
232 cpF = new CPMethodOrField(cpClass, nAndT);
233 cp_Field.add(cpF);
234 stringsToCpField.put(key, cpF);
235 }
236 return cpF;
237 }
238
239 public CPMethodOrField getCPField(final String owner, final String name, final String desc) {
240 return getCPField(getCPClass(owner), name, desc);
241 }
242
243 public CPMethodOrField getCPIMethod(final CPClass cpClass, final String name, final String desc) {
244 final String key = cpClass.toString() + ":" + name + ":" + desc;
245 CPMethodOrField cpIM = stringsToCpIMethod.get(key);
246 if (cpIM == null) {
247 final CPNameAndType nAndT = getCPNameAndType(name, desc);
248 cpIM = new CPMethodOrField(cpClass, nAndT);
249 cp_Imethod.add(cpIM);
250 stringsToCpIMethod.put(key, cpIM);
251 }
252 return cpIM;
253 }
254
255 public CPMethodOrField getCPIMethod(final String owner, final String name, final String desc) {
256 return getCPIMethod(getCPClass(owner), name, desc);
257 }
258
259 public CPMethodOrField getCPMethod(final CPClass cpClass, final String name, final String desc) {
260 final String key = cpClass.toString() + ":" + name + ":" + desc;
261 CPMethodOrField cpM = stringsToCpMethod.get(key);
262 if (cpM == null) {
263 final CPNameAndType nAndT = getCPNameAndType(name, desc);
264 cpM = new CPMethodOrField(cpClass, nAndT);
265 cp_Method.add(cpM);
266 stringsToCpMethod.put(key, cpM);
267 }
268 return cpM;
269 }
270
271 public CPMethodOrField getCPMethod(final String owner, final String name, final String desc) {
272 return getCPMethod(getCPClass(owner), name, desc);
273 }
274
275 public CPNameAndType getCPNameAndType(final String name, final String signature) {
276 final String descr = name + ":" + signature;
277 CPNameAndType nameAndType = stringsToCpNameAndType.get(descr);
278 if (nameAndType == null) {
279 nameAndType = new CPNameAndType(getCPUtf8(name), getCPSignature(signature));
280 stringsToCpNameAndType.put(descr, nameAndType);
281 cp_Descr.add(nameAndType);
282 }
283 return nameAndType;
284 }
285
286 public CPSignature getCPSignature(final String signature) {
287 if (signature == null) {
288 return null;
289 }
290 CPSignature cpS = stringsToCpSignature.get(signature);
291 if (cpS == null) {
292 final List<CPClass> cpClasses = new ArrayList<>();
293 CPUTF8 signatureUTF8;
294 if (signature.length() > 1 && signature.indexOf('L') != -1) {
295 final List<String> classes = new ArrayList<>();
296 final char[] chars = signature.toCharArray();
297 final StringBuilder signatureString = new StringBuilder();
298 for (int i = 0; i < chars.length; i++) {
299 signatureString.append(chars[i]);
300 if (chars[i] == 'L') {
301 final StringBuilder className = new StringBuilder();
302 for (int j = i + 1; j < chars.length; j++) {
303 final char c = chars[j];
304 if (!Character.isLetter(c) && !Character.isDigit(c) && c != '/' && c != '$' && c != '_') {
305 classes.add(className.toString());
306 i = j - 1;
307 break;
308 }
309 className.append(c);
310 }
311 }
312 }
313 removeCpUtf8(signature);
314 for (String className : classes) {
315 CPClass cpClass = null;
316 if (className != null) {
317 className = className.replace('.', '/');
318 cpClass = stringsToCpClass.get(className);
319 if (cpClass == null) {
320 final CPUTF8 cpUtf8 = getCPUtf8(className);
321 cpClass = new CPClass(cpUtf8);
322 cp_Class.add(cpClass);
323 stringsToCpClass.put(className, cpClass);
324 }
325 }
326 cpClasses.add(cpClass);
327 }
328
329 signatureUTF8 = getCPUtf8(signatureString.toString());
330 } else {
331 signatureUTF8 = getCPUtf8(signature);
332 }
333 cpS = new CPSignature(signature, signatureUTF8, cpClasses);
334 cp_Signature.add(cpS);
335 stringsToCpSignature.put(signature, cpS);
336 }
337 return cpS;
338 }
339
340 public CPUTF8 getCPUtf8(final String utf8) {
341 if (utf8 == null) {
342 return null;
343 }
344 CPUTF8 cpUtf8 = stringsToCpUtf8.get(utf8);
345 if (cpUtf8 == null) {
346 cpUtf8 = new CPUTF8(utf8);
347 cp_Utf8.add(cpUtf8);
348 stringsToCpUtf8.put(utf8, cpUtf8);
349 }
350 return cpUtf8;
351 }
352
353 @Override
354 public void pack(final OutputStream out) throws IOException, Pack200Exception {
355 PackingUtils.log("Writing constant pool bands...");
356 writeCpUtf8(out);
357 writeCpInt(out);
358 writeCpFloat(out);
359 writeCpLong(out);
360 writeCpDouble(out);
361 writeCpString(out);
362 writeCpClass(out);
363 writeCpSignature(out);
364 writeCpDescr(out);
365 writeCpMethodOrField(cp_Field, out, "cp_Field");
366 writeCpMethodOrField(cp_Method, out, "cp_Method");
367 writeCpMethodOrField(cp_Imethod, out, "cp_Imethod");
368 }
369
370 private void removeCpUtf8(final String string) {
371 final CPUTF8 utf8 = stringsToCpUtf8.get(string);
372 if (utf8 != null && stringsToCpClass.get(string) == null) {
373 stringsToCpUtf8.remove(string);
374 cp_Utf8.remove(utf8);
375 }
376 }
377
378 private void removeSignaturesFromCpUTF8() {
379 cp_Signature.forEach(signature -> {
380 final String sigStr = signature.getUnderlyingString();
381 final CPUTF8 utf8 = signature.getSignatureForm();
382 final String form = utf8.getUnderlyingString();
383 if (!sigStr.equals(form)) {
384 removeCpUtf8(sigStr);
385 }
386 });
387 }
388
389 private void writeCpClass(final OutputStream out) throws IOException, Pack200Exception {
390 PackingUtils.log("Writing " + cp_Class.size() + " Class entries...");
391 final int[] cpClass = new int[cp_Class.size()];
392 int i = 0;
393 for (final CPClass cpCl : cp_Class) {
394 cpClass[i] = cpCl.getIndexInCpUtf8();
395 i++;
396 }
397 final byte[] encodedBand = encodeBandInt("cpClass", cpClass, Codec.UDELTA5);
398 out.write(encodedBand);
399 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpClass[" + cpClass.length + "]");
400 }
401
402 private void writeCpDescr(final OutputStream out) throws IOException, Pack200Exception {
403 PackingUtils.log("Writing " + cp_Descr.size() + " Descriptor entries...");
404 final int[] cpDescrName = new int[cp_Descr.size()];
405 final int[] cpDescrType = new int[cp_Descr.size()];
406 int i = 0;
407 for (final CPNameAndType nameAndType : cp_Descr) {
408 cpDescrName[i] = nameAndType.getNameIndex();
409 cpDescrType[i] = nameAndType.getTypeIndex();
410 i++;
411 }
412
413 byte[] encodedBand = encodeBandInt("cp_Descr_Name", cpDescrName, Codec.DELTA5);
414 out.write(encodedBand);
415 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Name[" + cpDescrName.length + "]");
416
417 encodedBand = encodeBandInt("cp_Descr_Type", cpDescrType, Codec.UDELTA5);
418 out.write(encodedBand);
419 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Type[" + cpDescrType.length + "]");
420 }
421
422 private void writeCpDouble(final OutputStream out) throws IOException, Pack200Exception {
423 PackingUtils.log("Writing " + cp_Double.size() + " Double entries...");
424 final int[] highBits = new int[cp_Double.size()];
425 final int[] loBits = new int[cp_Double.size()];
426 int i = 0;
427 for (final CPDouble dbl : cp_Double) {
428 final long l = Double.doubleToLongBits(dbl.getDouble());
429 highBits[i] = (int) (l >> 32);
430 loBits[i] = (int) l;
431 i++;
432 }
433 byte[] encodedBand = encodeBandInt("cp_Double_hi", highBits, Codec.UDELTA5);
434 out.write(encodedBand);
435 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_hi[" + highBits.length + "]");
436
437 encodedBand = encodeBandInt("cp_Double_lo", loBits, Codec.DELTA5);
438 out.write(encodedBand);
439 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_lo[" + loBits.length + "]");
440 }
441
442 private void writeCpFloat(final OutputStream out) throws IOException, Pack200Exception {
443 PackingUtils.log("Writing " + cp_Float.size() + " Float entries...");
444 final int[] cpFloat = new int[cp_Float.size()];
445 int i = 0;
446 for (final CPFloat fl : cp_Float) {
447 cpFloat[i] = Float.floatToIntBits(fl.getFloat());
448 i++;
449 }
450 final byte[] encodedBand = encodeBandInt("cp_Float", cpFloat, Codec.UDELTA5);
451 out.write(encodedBand);
452 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Float[" + cpFloat.length + "]");
453 }
454
455 private void writeCpInt(final OutputStream out) throws IOException, Pack200Exception {
456 PackingUtils.log("Writing " + cp_Int.size() + " Integer entries...");
457 final int[] cpInt = new int[cp_Int.size()];
458 int i = 0;
459 for (final CPInt integer : cp_Int) {
460 cpInt[i] = integer.getInt();
461 i++;
462 }
463 final byte[] encodedBand = encodeBandInt("cp_Int", cpInt, Codec.UDELTA5);
464 out.write(encodedBand);
465 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Int[" + cpInt.length + "]");
466 }
467
468 private void writeCpLong(final OutputStream out) throws IOException, Pack200Exception {
469 PackingUtils.log("Writing " + cp_Long.size() + " Long entries...");
470 final int[] highBits = new int[cp_Long.size()];
471 final int[] loBits = new int[cp_Long.size()];
472 int i = 0;
473 for (final CPLong lng : cp_Long) {
474 final long l = lng.getLong();
475 highBits[i] = (int) (l >> 32);
476 loBits[i] = (int) l;
477 i++;
478 }
479 byte[] encodedBand = encodeBandInt("cp_Long_hi", highBits, Codec.UDELTA5);
480 out.write(encodedBand);
481 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_hi[" + highBits.length + "]");
482
483 encodedBand = encodeBandInt("cp_Long_lo", loBits, Codec.DELTA5);
484 out.write(encodedBand);
485 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_lo[" + loBits.length + "]");
486 }
487
488 private void writeCpMethodOrField(final Set<CPMethodOrField> cp, final OutputStream out, final String name) throws IOException, Pack200Exception {
489 PackingUtils.log("Writing " + cp.size() + " Method and Field entries...");
490 final int[] cp_methodOrField_class = new int[cp.size()];
491 final int[] cp_methodOrField_desc = new int[cp.size()];
492 int i = 0;
493 for (final CPMethodOrField mOrF : cp) {
494 cp_methodOrField_class[i] = mOrF.getClassIndex();
495 cp_methodOrField_desc[i] = mOrF.getDescIndex();
496 i++;
497 }
498 byte[] encodedBand = encodeBandInt(name + "_class", cp_methodOrField_class, Codec.DELTA5);
499 out.write(encodedBand);
500 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + name + "_class[" + cp_methodOrField_class.length + "]");
501
502 encodedBand = encodeBandInt(name + "_desc", cp_methodOrField_desc, Codec.UDELTA5);
503 out.write(encodedBand);
504 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + name + "_desc[" + cp_methodOrField_desc.length + "]");
505 }
506
507 private void writeCpSignature(final OutputStream out) throws IOException, Pack200Exception {
508 PackingUtils.log("Writing " + cp_Signature.size() + " Signature entries...");
509 final int[] cpSignatureForm = new int[cp_Signature.size()];
510 final List<CPClass> classes = new ArrayList<>();
511 int i = 0;
512 for (final CPSignature cpS : cp_Signature) {
513 classes.addAll(cpS.getClasses());
514 cpSignatureForm[i] = cpS.getIndexInCpUtf8();
515 i++;
516 }
517 final int[] cpSignatureClasses = new int[classes.size()];
518 Arrays.setAll(cpSignatureClasses, j -> classes.get(j).getIndex());
519
520 byte[] encodedBand = encodeBandInt("cpSignatureForm", cpSignatureForm, Codec.DELTA5);
521 out.write(encodedBand);
522 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpSignatureForm[" + cpSignatureForm.length + "]");
523
524 encodedBand = encodeBandInt("cpSignatureClasses", cpSignatureClasses, Codec.UDELTA5);
525 out.write(encodedBand);
526 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpSignatureClasses[" + cpSignatureClasses.length + "]");
527 }
528
529 private void writeCpString(final OutputStream out) throws IOException, Pack200Exception {
530 PackingUtils.log("Writing " + cp_String.size() + " String entries...");
531 final int[] cpString = new int[cp_String.size()];
532 int i = 0;
533 for (final CPString cpStr : cp_String) {
534 cpString[i] = cpStr.getIndexInCpUtf8();
535 i++;
536 }
537 final byte[] encodedBand = encodeBandInt("cpString", cpString, Codec.UDELTA5);
538 out.write(encodedBand);
539 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpString[" + cpString.length + "]");
540 }
541
542 private void writeCpUtf8(final OutputStream out) throws IOException, Pack200Exception {
543 PackingUtils.log("Writing " + cp_Utf8.size() + " UTF8 entries...");
544 final int[] cpUtf8Prefix = new int[cp_Utf8.size() - 2];
545 final int[] cpUtf8Suffix = new int[cp_Utf8.size() - 1];
546 final List<Character> chars = new ArrayList<>();
547 final List<Integer> bigSuffix = new ArrayList<>();
548 final List<Character> bigChars = new ArrayList<>();
549 final Object[] cpUtf8Array = cp_Utf8.toArray();
550 final String first = ((CPUTF8) cpUtf8Array[1]).getUnderlyingString();
551 cpUtf8Suffix[0] = first.length();
552 addCharacters(chars, first.toCharArray());
553 for (int i = 2; i < cpUtf8Array.length; i++) {
554 final char[] previous = ((CPUTF8) cpUtf8Array[i - 1]).getUnderlyingString().toCharArray();
555 String currentStr = ((CPUTF8) cpUtf8Array[i]).getUnderlyingString();
556 final char[] current = currentStr.toCharArray();
557 int prefix = 0;
558 for (int j = 0; j < previous.length; j++) {
559 if (previous[j] != current[j]) {
560 break;
561 }
562 prefix++;
563 }
564 cpUtf8Prefix[i - 2] = prefix;
565 currentStr = currentStr.substring(prefix);
566 final char[] suffix = currentStr.toCharArray();
567 if (suffix.length > 1000) {
568
569 cpUtf8Suffix[i - 1] = 0;
570 bigSuffix.add(Integer.valueOf(suffix.length));
571 addCharacters(bigChars, suffix);
572 } else {
573 cpUtf8Suffix[i - 1] = suffix.length;
574 addCharacters(chars, suffix);
575 }
576 }
577 final int[] cpUtf8Chars = new int[chars.size()];
578 final int[] cpUtf8BigSuffix = new int[bigSuffix.size()];
579 final int[][] cpUtf8BigChars = new int[bigSuffix.size()][];
580 Arrays.setAll(cpUtf8Chars, i -> chars.get(i).charValue());
581 for (int i = 0; i < cpUtf8BigSuffix.length; i++) {
582 final int numBigChars = bigSuffix.get(i).intValue();
583 cpUtf8BigSuffix[i] = numBigChars;
584 cpUtf8BigChars[i] = new int[numBigChars];
585 Arrays.setAll(cpUtf8BigChars[i], j -> bigChars.remove(0).charValue());
586 }
587
588 byte[] encodedBand = encodeBandInt("cpUtf8Prefix", cpUtf8Prefix, Codec.DELTA5);
589 out.write(encodedBand);
590 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Prefix[" + cpUtf8Prefix.length + "]");
591
592 encodedBand = encodeBandInt("cpUtf8Suffix", cpUtf8Suffix, Codec.UNSIGNED5);
593 out.write(encodedBand);
594 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Suffix[" + cpUtf8Suffix.length + "]");
595
596 encodedBand = encodeBandInt("cpUtf8Chars", cpUtf8Chars, Codec.CHAR3);
597 out.write(encodedBand);
598 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Chars[" + cpUtf8Chars.length + "]");
599
600 encodedBand = encodeBandInt("cpUtf8BigSuffix", cpUtf8BigSuffix, Codec.DELTA5);
601 out.write(encodedBand);
602 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigSuffix[" + cpUtf8BigSuffix.length + "]");
603
604 for (int i = 0; i < cpUtf8BigChars.length; i++) {
605 encodedBand = encodeBandInt("cpUtf8BigChars " + i, cpUtf8BigChars[i], Codec.DELTA5);
606 out.write(encodedBand);
607 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigChars" + i + "[" + cpUtf8BigChars[i].length + "]");
608 }
609 }
610
611 }