StringIdsSection.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
1/*
2 * Copyright (C) 2007 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.Constant;
20import com.android.dx.rop.cst.CstNat;
21import com.android.dx.rop.cst.CstString;
22import com.android.dx.util.AnnotatedOutput;
23import com.android.dx.util.Hex;
24
25import java.util.Collection;
26import java.util.TreeMap;
27
28/**
29 * Strings list section of a {@code .dex} file.
30 */
31public final class StringIdsSection
32        extends UniformItemSection {
33    /**
34     * {@code non-null;} map from string constants to {@link
35     * StringIdItem} instances
36     */
37    private final TreeMap<CstString, StringIdItem> strings;
38
39    /**
40     * Constructs an instance. The file offset is initially unknown.
41     *
42     * @param file {@code non-null;} file that this instance is part of
43     */
44    public StringIdsSection(DexFile file) {
45        super("string_ids", file, 4);
46
47        strings = new TreeMap<CstString, StringIdItem>();
48    }
49
50    /** {@inheritDoc} */
51    @Override
52    public Collection<? extends Item> items() {
53        return strings.values();
54    }
55
56    /** {@inheritDoc} */
57    @Override
58    public IndexedItem get(Constant cst) {
59        if (cst == null) {
60            throw new NullPointerException("cst == null");
61        }
62
63        throwIfNotPrepared();
64
65        IndexedItem result = strings.get((CstString) cst);
66
67        if (result == null) {
68            throw new IllegalArgumentException("not found");
69        }
70
71        return result;
72    }
73
74    /**
75     * Writes the portion of the file header that refers to this instance.
76     *
77     * @param out {@code non-null;} where to write
78     */
79    public void writeHeaderPart(AnnotatedOutput out) {
80        throwIfNotPrepared();
81
82        int sz = strings.size();
83        int offset = (sz == 0) ? 0 : getFileOffset();
84
85        if (out.annotates()) {
86            out.annotate(4, "string_ids_size: " + Hex.u4(sz));
87            out.annotate(4, "string_ids_off:  " + Hex.u4(offset));
88        }
89
90        out.writeInt(sz);
91        out.writeInt(offset);
92    }
93
94    /**
95     * Interns an element into this instance.
96     *
97     * @param string {@code non-null;} the string to intern, as a regular Java
98     * {@code String}
99     * @return {@code non-null;} the interned string
100     */
101    public StringIdItem intern(String string) {
102        return intern(new StringIdItem(new CstString(string)));
103    }
104
105    /**
106     * Interns an element into this instance.
107     *
108     * @param string {@code non-null;} the string to intern, as a constant
109     * @return {@code non-null;} the interned string
110     */
111    public StringIdItem intern(CstString string) {
112        return intern(new StringIdItem(string));
113    }
114
115    /**
116     * Interns an element into this instance.
117     *
118     * @param string {@code non-null;} the string to intern
119     * @return {@code non-null;} the interned string
120     */
121    public StringIdItem intern(StringIdItem string) {
122        if (string == null) {
123            throw new NullPointerException("string == null");
124        }
125
126        throwIfPrepared();
127
128        CstString value = string.getValue();
129        StringIdItem already = strings.get(value);
130
131        if (already != null) {
132            return already;
133        }
134
135        strings.put(value, string);
136        return string;
137    }
138
139    /**
140     * Interns the components of a name-and-type into this instance.
141     *
142     * @param nat {@code non-null;} the name-and-type
143     */
144    public void intern(CstNat nat) {
145        intern(nat.getName());
146        intern(nat.getDescriptor());
147    }
148
149    /**
150     * Gets the index of the given string, which must have been added
151     * to this instance.
152     *
153     * @param string {@code non-null;} the string to look up
154     * @return {@code >= 0;} the string's index
155     */
156    public int indexOf(CstString string) {
157        if (string == null) {
158            throw new NullPointerException("string == null");
159        }
160
161        throwIfNotPrepared();
162
163        StringIdItem s = strings.get(string);
164
165        if (s == null) {
166            throw new IllegalArgumentException("not found");
167        }
168
169        return s.getIndex();
170    }
171
172    /** {@inheritDoc} */
173    @Override
174    protected void orderItems() {
175        int idx = 0;
176
177        for (StringIdItem s : strings.values()) {
178            s.setIndex(idx);
179            idx++;
180        }
181    }
182}
183