1081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson/* 2081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Copyright (C) 2011 The Android Open Source Project 3081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 4081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * you may not use this file except in compliance with the License. 6081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * You may obtain a copy of the License at 7081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 8081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * 10081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Unless required by applicable law or agreed to in writing, software 11081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * See the License for the specific language governing permissions and 14081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * limitations under the License. 15081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */ 16081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 17081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonpackage com.android.dx.merge; 18081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 19081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonimport com.android.dx.dex.TableOfContents; 20bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.io.Annotation; 21dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.ClassDef; 22dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.DexBuffer; 23bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.io.EncodedValue; 24bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.io.EncodedValueReader; 25dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.FieldId; 26dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.MethodId; 27dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilsonimport com.android.dx.io.ProtoId; 28bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteArrayAnnotatedOutput; 29bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteInput; 30bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteOutput; 31bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.Leb128Utils; 32bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.Unsigned; 33cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilsonimport java.util.HashMap; 34081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 35081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson/** 36081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * Maps the index offsets from one dex file to those in another. For example, if 37081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * you have string #5 in the old dex file, its position in the new dex file is 38081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson * {@code strings[5]}. 39081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson */ 40081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonpublic final class IndexMap { 41dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson private final DexBuffer target; 42081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson public final int[] stringIds; 43dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public final short[] typeIds; 44dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public final short[] protoIds; 45dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public final short[] fieldIds; 46dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public final short[] methodIds; 47d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson private final HashMap<Integer, Integer> typeListOffsets; 48bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson private final HashMap<Integer, Integer> annotationOffsets; 49d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson private final HashMap<Integer, Integer> annotationSetOffsets; 50d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson private final HashMap<Integer, Integer> annotationDirectoryOffsets; 51fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson private final HashMap<Integer, Integer> staticValuesOffsets; 52081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 53dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public IndexMap(DexBuffer target, TableOfContents tableOfContents) { 54dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.target = target; 55dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.stringIds = new int[tableOfContents.stringIds.size]; 56dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.typeIds = new short[tableOfContents.typeIds.size]; 57dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.protoIds = new short[tableOfContents.protoIds.size]; 58dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.fieldIds = new short[tableOfContents.fieldIds.size]; 59dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson this.methodIds = new short[tableOfContents.methodIds.size]; 60cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson this.typeListOffsets = new HashMap<Integer, Integer>(); 61bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson this.annotationOffsets = new HashMap<Integer, Integer>(); 6220d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson this.annotationSetOffsets = new HashMap<Integer, Integer>(); 6320d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson this.annotationDirectoryOffsets = new HashMap<Integer, Integer>(); 64fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson this.staticValuesOffsets = new HashMap<Integer, Integer>(); 65cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson 66cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson /* 67fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson * A type list, annotation set, annotation directory, or static value at 68fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson * offset 0 is always empty. Always map offset 0 to 0. 69cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson */ 70cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson this.typeListOffsets.put(0, 0); 7120d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson this.annotationSetOffsets.put(0, 0); 7220d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson this.annotationDirectoryOffsets.put(0, 0); 73fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson this.staticValuesOffsets.put(0, 0); 74081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 75081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson 76d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson public void putTypeListOffset(int oldOffset, int newOffset) { 77d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if (oldOffset <= 0 || newOffset <= 0) { 78d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson throw new IllegalArgumentException(); 79d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 80d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson typeListOffsets.put(oldOffset, newOffset); 81d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 82d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson 83bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public void putAnnotationOffset(int oldOffset, int newOffset) { 84bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson if (oldOffset <= 0 || newOffset <= 0) { 85bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson throw new IllegalArgumentException(); 86bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 87bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson annotationOffsets.put(oldOffset, newOffset); 88bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 89bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 90d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson public void putAnnotationSetOffset(int oldOffset, int newOffset) { 91d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if (oldOffset <= 0 || newOffset <= 0) { 92d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson throw new IllegalArgumentException(); 93d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 94d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson annotationSetOffsets.put(oldOffset, newOffset); 95d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 96d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson 97d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson public void putAnnotationDirectoryOffset(int oldOffset, int newOffset) { 98d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson if (oldOffset <= 0 || newOffset <= 0) { 99d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson throw new IllegalArgumentException(); 100d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 101d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson annotationDirectoryOffsets.put(oldOffset, newOffset); 102d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson } 103d1e1668224cde06bbe5ad8953c7fb86d1d0d40e4Jesse Wilson 104fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson public void putStaticValuesOffset(int oldOffset, int newOffset) { 105fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson if (oldOffset <= 0 || newOffset <= 0) { 106fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson throw new IllegalArgumentException(); 107fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson } 108fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson staticValuesOffsets.put(oldOffset, newOffset); 109fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson } 110fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson 111dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public int adjustString(int stringIndex) { 112dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return stringIndex == ClassDef.NO_INDEX ? ClassDef.NO_INDEX : stringIds[stringIndex]; 113dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 114dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 115bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public int adjustType(int typeIndex) { 116bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return (typeIndex == ClassDef.NO_INDEX) ? ClassDef.NO_INDEX : (typeIds[typeIndex] & 0xffff); 117dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 118dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 119cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson public TypeList adjustTypeList(TypeList typeList) { 120cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson if (typeList == TypeList.EMPTY) { 121cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson return typeList; 122cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson } 123cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson short[] types = typeList.getTypes().clone(); 124cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson for (int i = 0; i < types.length; i++) { 125bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson types[i] = (short) adjustType(types[i]); 126081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 127cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson return new TypeList(target, types); 128dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 129dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 130bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public int adjustProto(int protoIndex) { 131bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return protoIds[protoIndex] & 0xffff; 132dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 133dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 134bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public int adjustField(int fieldIndex) { 135bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return fieldIds[fieldIndex] & 0xffff; 136dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 137dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 138bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public int adjustMethod(int methodIndex) { 139bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return methodIds[methodIndex] & 0xffff; 140dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 141dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 142cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson public int adjustTypeListOffset(int typeListOffset) { 143cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson return typeListOffsets.get(typeListOffset); 144cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson } 145cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson 146bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public int adjustAnnotation(int annotationOffset) { 147bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return annotationOffsets.get(annotationOffset); 148bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 149bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 15020d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson public int adjustAnnotationSet(int annotationSetOffset) { 15120d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson return annotationSetOffsets.get(annotationSetOffset); 15220d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson } 15320d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson 15420d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson public int adjustAnnotationDirectory(int annotationDirectoryOffset) { 15520d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson return annotationDirectoryOffsets.get(annotationDirectoryOffset); 15620d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson } 15720d269ea2a9e8d41b298134f3937c6d959288b53Jesse Wilson 158fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson public int adjustStaticValues(int staticValuesOffset) { 159fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson return staticValuesOffsets.get(staticValuesOffset); 160fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson } 161fa3b293a068fd521a6ba6019a051ad502dfaca55Jesse Wilson 162dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public MethodId adjust(MethodId methodId) { 163dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return new MethodId(target, 164dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustType(methodId.getDeclaringClassIndex()), 165dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustProto(methodId.getProtoIndex()), 166dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustString(methodId.getNameIndex())); 167dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 168dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 169dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public FieldId adjust(FieldId fieldId) { 170dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return new FieldId(target, 171dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustType(fieldId.getDeclaringClassIndex()), 172dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustType(fieldId.getTypeIndex()), 173dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustString(fieldId.getNameIndex())); 174dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 175dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 176dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 177dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public ProtoId adjust(ProtoId protoId) { 178dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return new ProtoId(target, 179dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustString(protoId.getShortyIndex()), 180dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson adjustType(protoId.getReturnTypeIndex()), 181cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson adjustTypeListOffset(protoId.getParametersOffset())); 182dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 183dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 184dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public ClassDef adjust(ClassDef classDef) { 185dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return new ClassDef(target, classDef.getOffset(), adjustType(classDef.getTypeIndex()), 186dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson classDef.getAccessFlags(), adjustType(classDef.getSupertypeIndex()), 187cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson adjustTypeListOffset(classDef.getInterfacesOffset()), classDef.getSourceFileIndex(), 188cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson classDef.getAnnotationsOffset(), classDef.getClassDataOffset(), 189cdef3ed061e2a045d956ea613556a67f9ac6e9d0Jesse Wilson classDef.getStaticValuesOffset()); 190dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson } 191dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson 192dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson public SortableType adjust(SortableType sortableType) { 193dc8ad6cbf19b62d8c50527a0a38fe82b937370f1Jesse Wilson return new SortableType(sortableType.getBuffer(), adjust(sortableType.getClassDef())); 194081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson } 195bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 196bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public EncodedValue adjustEncodedValue(EncodedValue encodedValue) { 197bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(32); 198bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson new EncodedValueTransformer(encodedValue, out).readValue(); 199bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return new EncodedValue(out.toByteArray()); 200bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 201bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 202bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public EncodedValue adjustEncodedArray(EncodedValue encodedArray) { 203bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(32); 204bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson new EncodedValueTransformer(encodedArray, out).readArray(); 205bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return new EncodedValue(out.toByteArray()); 206bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 207bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 208bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public Annotation adjust(Annotation annotation) { 209bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson int[] names = annotation.getNames().clone(); 210bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson EncodedValue[] values = annotation.getValues().clone(); 211bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson for (int i = 0; i < names.length; i++) { 212bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson names[i] = adjustString(names[i]); 213bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson values[i] = adjustEncodedValue(values[i]); 214bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 215bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson return new Annotation(target, annotation.getVisibility(), 216bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson adjustType(annotation.getTypeIndex()), names, values); 217bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 218bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 219bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson /** 220bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson * Adjust an encoded value or array. 221bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson */ 222bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson private final class EncodedValueTransformer extends EncodedValueReader { 223bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson private final ByteOutput out; 224bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 225bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson public EncodedValueTransformer(EncodedValue encodedValue, ByteOutput out) { 226bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson super(encodedValue); 227bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson this.out = out; 228bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 229bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 230bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitArray(int size) { 231bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson Leb128Utils.writeUnsignedLeb128(out, size); 232bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 233bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 234bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitAnnotation(int typeIndex, int size) { 235bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson Leb128Utils.writeUnsignedLeb128(out, adjustType(typeIndex)); 236bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson Leb128Utils.writeUnsignedLeb128(out, size); 237bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 238bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 239bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitAnnotationName(int index) { 240bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson Leb128Utils.writeUnsignedLeb128(out, adjustString(index)); 241bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 242bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 243bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitPrimitive(int argAndType, int type, int arg, int size) { 244bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 245bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson copyBytes(in, out, size); 246bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 247bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 248bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitString(int type, int index) { 249bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson writeTypeAndSizeAndIndex(type, adjustString(index)); 250bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 251bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 252bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitType(int type, int index) { 253bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson writeTypeAndSizeAndIndex(type, adjustType(index)); 254bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 255bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 256bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitField(int type, int index) { 257bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson writeTypeAndSizeAndIndex(type, adjustField(index)); 258bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 259bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 260bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitMethod(int type, int index) { 261bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson writeTypeAndSizeAndIndex(type, adjustMethod(index)); 262bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 263bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 264bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitArrayValue(int argAndType) { 265bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 266bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 267bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 268bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitAnnotationValue(int argAndType) { 269bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 270bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 271bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 272bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitEncodedBoolean(int argAndType) { 273bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 274bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 275bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 276bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson protected void visitEncodedNull(int argAndType) { 277bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 278bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 279bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 280bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson private void writeTypeAndSizeAndIndex(int type, int index) { 281bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson int byteCount; 282bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson if (Unsigned.compare(index, 0xff) <= 0) { 283bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson byteCount = 1; 284bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } else if (Unsigned.compare(index, 0xffff) <= 0) { 285bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson byteCount = 2; 286bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } else if (Unsigned.compare(index, 0xffffff) <= 0) { 287bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson byteCount = 3; 288bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } else { 289bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson byteCount = 4; 290bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 291bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson int argAndType = ((byteCount - 1) << 5) | type; 292bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(argAndType); 293bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 294bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson for (int i = 0; i < byteCount; i++) { 295bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(index & 0xff); 296bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson index >>>= 8; 297bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 298bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 299bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson 300bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson private void copyBytes(ByteInput in, ByteOutput out, int size) { 301bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson for (int i = 0; i < size; i++) { 302bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson out.writeByte(in.readByte()); 303bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 304bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 305bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson } 306081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson} 307