ProtoIdItem.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
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.dex.SizeOf;
20import com.android.dx.rop.cst.CstString;
21import com.android.dx.rop.type.Prototype;
22import com.android.dx.rop.type.StdTypeList;
23import com.android.dx.rop.type.Type;
24import com.android.dx.util.AnnotatedOutput;
25import com.android.dx.util.Hex;
26
27/**
28 * Representation of a method prototype reference inside a Dalvik file.
29 */
30public final class ProtoIdItem extends IndexedItem {
31    /** {@code non-null;} the wrapped prototype */
32    private final Prototype prototype;
33
34    /** {@code non-null;} the short-form of the prototype */
35    private final CstString shortForm;
36
37    /**
38     * {@code null-ok;} the list of parameter types or {@code null} if this
39     * prototype has no parameters
40     */
41    private TypeListItem parameterTypes;
42
43    /**
44     * Constructs an instance.
45     *
46     * @param prototype {@code non-null;} the constant for the prototype
47     */
48    public ProtoIdItem(Prototype prototype) {
49        if (prototype == null) {
50            throw new NullPointerException("prototype == null");
51        }
52
53        this.prototype = prototype;
54        this.shortForm = makeShortForm(prototype);
55
56        StdTypeList parameters = prototype.getParameterTypes();
57        this.parameterTypes = (parameters.size() == 0) ? null
58            : new TypeListItem(parameters);
59    }
60
61    /**
62     * Creates the short-form of the given prototype.
63     *
64     * @param prototype {@code non-null;} the prototype
65     * @return {@code non-null;} the short form
66     */
67    private static CstString makeShortForm(Prototype prototype) {
68        StdTypeList parameters = prototype.getParameterTypes();
69        int size = parameters.size();
70        StringBuilder sb = new StringBuilder(size + 1);
71
72        sb.append(shortFormCharFor(prototype.getReturnType()));
73
74        for (int i = 0; i < size; i++) {
75            sb.append(shortFormCharFor(parameters.getType(i)));
76        }
77
78        return new CstString(sb.toString());
79    }
80
81    /**
82     * Gets the short-form character for the given type.
83     *
84     * @param type {@code non-null;} the type
85     * @return the corresponding short-form character
86     */
87    private static char shortFormCharFor(Type type) {
88        char descriptorChar = type.getDescriptor().charAt(0);
89
90        if (descriptorChar == '[') {
91            return 'L';
92        }
93
94        return descriptorChar;
95    }
96
97    /** {@inheritDoc} */
98    @Override
99    public ItemType itemType() {
100        return ItemType.TYPE_PROTO_ID_ITEM;
101    }
102
103    /** {@inheritDoc} */
104    @Override
105    public int writeSize() {
106        return SizeOf.PROTO_ID_ITEM;
107    }
108
109    /** {@inheritDoc} */
110    @Override
111    public void addContents(DexFile file) {
112        StringIdsSection stringIds = file.getStringIds();
113        TypeIdsSection typeIds = file.getTypeIds();
114        MixedItemSection typeLists = file.getTypeLists();
115
116        typeIds.intern(prototype.getReturnType());
117        stringIds.intern(shortForm);
118
119        if (parameterTypes != null) {
120            parameterTypes = typeLists.intern(parameterTypes);
121        }
122    }
123
124    /** {@inheritDoc} */
125    @Override
126    public void writeTo(DexFile file, AnnotatedOutput out) {
127        int shortyIdx = file.getStringIds().indexOf(shortForm);
128        int returnIdx = file.getTypeIds().indexOf(prototype.getReturnType());
129        int paramsOff = OffsettedItem.getAbsoluteOffsetOr0(parameterTypes);
130
131        if (out.annotates()) {
132            StringBuilder sb = new StringBuilder();
133            sb.append(prototype.getReturnType().toHuman());
134            sb.append(" proto(");
135
136            StdTypeList params = prototype.getParameterTypes();
137            int size = params.size();
138
139            for (int i = 0; i < size; i++) {
140                if (i != 0) {
141                    sb.append(", ");
142                }
143                sb.append(params.getType(i).toHuman());
144            }
145
146            sb.append(")");
147            out.annotate(0, indexString() + ' ' + sb.toString());
148            out.annotate(4, "  shorty_idx:      " + Hex.u4(shortyIdx) +
149                    " // " + shortForm.toQuoted());
150            out.annotate(4, "  return_type_idx: " + Hex.u4(returnIdx) +
151                    " // " + prototype.getReturnType().toHuman());
152            out.annotate(4, "  parameters_off:  " + Hex.u4(paramsOff));
153        }
154
155        out.writeInt(shortyIdx);
156        out.writeInt(returnIdx);
157        out.writeInt(paramsOff);
158    }
159}
160