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
17package com.android.dx.dex.file;
18
19import com.android.dx.rop.cst.CstArray;
20import com.android.dx.util.ByteArrayAnnotatedOutput;
21import com.android.dx.util.AnnotatedOutput;
22
23/**
24 * Encoded array of constant values.
25 */
26public 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     */
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
61    public ItemType itemType() {
62        return ItemType.TYPE_ENCODED_ARRAY_ITEM;
63    }
64
65    /** {@inheritDoc} */
66    @Override
67    public int hashCode() {
68        return array.hashCode();
69    }
70
71    /** {@inheritDoc} */
72    @Override
73    protected int compareTo0(OffsettedItem other) {
74        EncodedArrayItem otherArray = (EncodedArrayItem) other;
75
76        return array.compareTo(otherArray.array);
77    }
78
79    /** {@inheritDoc} */
80    @Override
81    public String toHuman() {
82        return array.toHuman();
83    }
84
85    /** {@inheritDoc} */
86    public void addContents(DexFile file) {
87        ValueEncoder.addContents(file, array);
88    }
89
90    /** {@inheritDoc} */
91    @Override
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
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