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.dx.dex.file;
18 
19 import com.android.dx.rop.cst.CstArray;
20 import com.android.dx.util.ByteArrayAnnotatedOutput;
21 import com.android.dx.util.AnnotatedOutput;
22 
23 /**
24  * Encoded array of constant values.
25  */
26 public final class EncodedArrayItem extends OffsettedItem {
27     /** the required alignment for instances of this class */
28     private static final int ALIGNMENT = 1;
29 
30     /** {@code non-null;} the array to represent */
31     private final CstArray array;
32 
33     /**
34      * {@code null-ok;} encoded form, ready for writing to a file; set during
35      * {@link #place0}
36      */
37     private byte[] encodedForm;
38 
39     /**
40      * Constructs an instance.
41      *
42      * @param array {@code non-null;} array to represent
43      */
EncodedArrayItem(CstArray array)44     public EncodedArrayItem(CstArray array) {
45         /*
46          * The write size isn't known up-front because (the variable-lengthed)
47          * leb128 type is used to represent some things.
48          */
49         super(ALIGNMENT, -1);
50 
51         if (array == null) {
52             throw new NullPointerException("array == null");
53         }
54 
55         this.array = array;
56         this.encodedForm = null;
57     }
58 
59     /** {@inheritDoc} */
60     @Override
itemType()61     public ItemType itemType() {
62         return ItemType.TYPE_ENCODED_ARRAY_ITEM;
63     }
64 
65     /** {@inheritDoc} */
66     @Override
hashCode()67     public int hashCode() {
68         return array.hashCode();
69     }
70 
71     /** {@inheritDoc} */
72     @Override
compareTo0(OffsettedItem other)73     protected int compareTo0(OffsettedItem other) {
74         EncodedArrayItem otherArray = (EncodedArrayItem) other;
75 
76         return array.compareTo(otherArray.array);
77     }
78 
79     /** {@inheritDoc} */
80     @Override
toHuman()81     public String toHuman() {
82         return array.toHuman();
83     }
84 
85     /** {@inheritDoc} */
addContents(DexFile file)86     public void addContents(DexFile file) {
87         ValueEncoder.addContents(file, array);
88     }
89 
90     /** {@inheritDoc} */
91     @Override
place0(Section addedTo, int offset)92     protected void place0(Section addedTo, int offset) {
93         // Encode the data and note the size.
94 
95         ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
96         ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out);
97 
98         encoder.writeArray(array, false);
99         encodedForm = out.toByteArray();
100         setWriteSize(encodedForm.length);
101     }
102 
103     /** {@inheritDoc} */
104     @Override
writeTo0(DexFile file, AnnotatedOutput out)105     protected void writeTo0(DexFile file, AnnotatedOutput out) {
106         boolean annotates = out.annotates();
107 
108         if (annotates) {
109             out.annotate(0, offsetString() + " encoded array");
110 
111             /*
112              * The output is to be annotated, so redo the work previously
113              * done by place0(), except this time annotations will actually
114              * get emitted.
115              */
116             ValueEncoder encoder = new ValueEncoder(file, out);
117             encoder.writeArray(array, true);
118         } else {
119             out.write(encodedForm);
120         }
121     }
122 }
123