1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dexgen.dex.file; 18 19 import com.android.dexgen.rop.annotation.Annotation; 20 import com.android.dexgen.rop.annotation.AnnotationVisibility; 21 import com.android.dexgen.rop.annotation.NameValuePair; 22 import com.android.dexgen.rop.cst.Constant; 23 import com.android.dexgen.rop.cst.CstAnnotation; 24 import com.android.dexgen.rop.cst.CstArray; 25 import com.android.dexgen.rop.cst.CstUtf8; 26 import com.android.dexgen.util.AnnotatedOutput; 27 import com.android.dexgen.util.ByteArrayAnnotatedOutput; 28 29 import java.util.Arrays; 30 import java.util.Comparator; 31 32 /** 33 * Encoded array of constant values. 34 */ 35 public final class EncodedArrayItem extends OffsettedItem { 36 /** the required alignment for instances of this class */ 37 private static final int ALIGNMENT = 1; 38 39 /** {@code non-null;} the array to represent */ 40 private final CstArray array; 41 42 /** 43 * {@code null-ok;} encoded form, ready for writing to a file; set during 44 * {@link #place0} 45 */ 46 private byte[] encodedForm; 47 48 /** 49 * Constructs an instance. 50 * 51 * @param array {@code non-null;} array to represent 52 */ 53 public EncodedArrayItem(CstArray array) { 54 /* 55 * The write size isn't known up-front because (the variable-lengthed) 56 * leb128 type is used to represent some things. 57 */ 58 super(ALIGNMENT, -1); 59 60 if (array == null) { 61 throw new NullPointerException("array == null"); 62 } 63 64 this.array = array; 65 this.encodedForm = null; 66 } 67 68 /** {@inheritDoc} */ 69 @Override 70 public ItemType itemType() { 71 return ItemType.TYPE_ENCODED_ARRAY_ITEM; 72 } 73 74 /** {@inheritDoc} */ 75 @Override 76 public int hashCode() { 77 return array.hashCode(); 78 } 79 80 /** {@inheritDoc} */ 81 @Override 82 protected int compareTo0(OffsettedItem other) { 83 EncodedArrayItem otherArray = (EncodedArrayItem) other; 84 85 return array.compareTo(otherArray.array); 86 } 87 88 /** {@inheritDoc} */ 89 @Override 90 public String toHuman() { 91 return array.toHuman(); 92 } 93 94 /** {@inheritDoc} */ 95 public void addContents(DexFile file) { 96 ValueEncoder.addContents(file, array); 97 } 98 99 /** {@inheritDoc} */ 100 @Override 101 protected void place0(Section addedTo, int offset) { 102 // Encode the data and note the size. 103 104 ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); 105 ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out); 106 107 encoder.writeArray(array, false); 108 encodedForm = out.toByteArray(); 109 setWriteSize(encodedForm.length); 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 protected void writeTo0(DexFile file, AnnotatedOutput out) { 115 boolean annotates = out.annotates(); 116 117 if (annotates) { 118 out.annotate(0, offsetString() + " encoded array"); 119 120 /* 121 * The output is to be annotated, so redo the work previously 122 * done by place0(), except this time annotations will actually 123 * get emitted. 124 */ 125 ValueEncoder encoder = new ValueEncoder(file, out); 126 encoder.writeArray(array, true); 127 } else { 128 out.write(encodedForm); 129 } 130 } 131 } 132