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.dexgen.dex.file;
18
19import com.android.dexgen.rop.annotation.Annotation;
20import com.android.dexgen.rop.annotation.AnnotationVisibility;
21import com.android.dexgen.rop.annotation.NameValuePair;
22import com.android.dexgen.rop.cst.Constant;
23import com.android.dexgen.rop.cst.CstAnnotation;
24import com.android.dexgen.rop.cst.CstArray;
25import com.android.dexgen.rop.cst.CstUtf8;
26import com.android.dexgen.util.AnnotatedOutput;
27import com.android.dexgen.util.ByteArrayAnnotatedOutput;
28
29import java.util.Arrays;
30import java.util.Comparator;
31
32/**
33 * Encoded array of constant values.
34 */
35public 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