StringIdItem.java revision 58e4b792b8c6103416808c13eedd926cff118c80
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2010 Ben Gruver (JesusFreke)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.dexlib;
30
31import org.jf.dexlib.Util.AnnotatedOutput;
32import org.jf.dexlib.Util.Input;
33import org.jf.dexlib.Util.Utf8Utils;
34
35import javax.annotation.Nullable;
36
37public class StringIdItem extends Item<StringIdItem> {
38    private StringDataItem stringDataItem;
39
40   /**
41     * Creates a new uninitialized <code>StringIdItem</code>
42     * @param dexFile The <code>DexFile</code> that this item belongs to
43     */
44    protected StringIdItem(DexFile dexFile) {
45        super(dexFile);
46    }
47
48    /**
49     * Creates a new <code>StringIdItem</code> for the given <code>StringDataItem</code>
50     * @param dexFile The <code>DexFile</code> that this item belongs to
51     * @param stringDataItem The <code>StringDataItem</code> that this <code>StringIdItem</code> represents
52     */
53    protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
54        super(dexFile);
55        this.stringDataItem = stringDataItem;
56    }
57
58    /**
59     * Returns a <code>StringIdItem</code> for the given values, and that has been interned into
60     * the given <code>DexFile</code>
61     * @param dexFile The <code>DexFile</code> that this item will belong to
62     * @param stringValue The string value that this item represents
63     * @return a <code>StringIdItem</code> for the given values, and that has been interned into
64     * the given <code>DexFile</code>
65     */
66    public static StringIdItem internStringIdItem(DexFile dexFile, String stringValue) {
67        StringDataItem stringDataItem = StringDataItem.internStringDataItem(dexFile, stringValue);
68        if (stringDataItem == null) {
69            return null;
70        }
71        StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
72        return dexFile.StringIdsSection.intern(stringIdItem);
73    }
74
75    /**
76     * Looks up the <code>StringIdItem</code> from the given <code>DexFile</code> for the given
77     * string value
78     * @param dexFile the <code>Dexfile</code> to find the string value in
79     * @param stringValue The string value to look up
80     * @return a <code>StringIdItem</code> from the given <code>DexFile</code> for the given
81     * string value, or null if it doesn't exist
82     */
83    public static StringIdItem lookupStringIdItem(DexFile dexFile, String stringValue) {
84        StringDataItem stringDataItem = StringDataItem.lookupStringDataItem(dexFile, stringValue);
85        if (stringDataItem == null) {
86            return null;
87        }
88        StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
89        return dexFile.StringIdsSection.getInternedItem(stringIdItem);
90    }
91
92    /** {@inheritDoc} */
93    protected void readItem(Input in, ReadContext readContext) {
94        int stringDataOffset = in.readInt();
95
96        stringDataItem = (StringDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_STRING_DATA_ITEM,
97                stringDataOffset);
98    }
99
100    /** {@inheritDoc} */
101    protected int placeItem(int offset) {
102        return offset + 4;
103    }
104
105    /** {@inheritDoc} */
106    protected void writeItem(AnnotatedOutput out) {
107        if (out.annotates()) {
108            out.annotate(4, stringDataItem.getConciseIdentity());
109        }
110
111        out.writeInt(stringDataItem.getOffset());
112    }
113
114    /** {@inheritDoc} */
115    public ItemType getItemType() {
116        return ItemType.TYPE_STRING_ID_ITEM;
117    }
118
119    /** {@inheritDoc} */
120    public String getConciseIdentity() {
121        return "string_id_item: " + Utf8Utils.escapeString(getStringValue());
122    }
123
124    /** {@inheritDoc} */
125    public int compareTo(StringIdItem o) {
126        //sort by the string value
127        return getStringValue().compareTo(o.getStringValue());
128    }
129
130    /**
131     * Get the <code>String</code> value that this <code>StringIdItem</code> represents
132     * @return the <code>String</code> value that this <code>StringIdItem</code> represents
133     */
134    public String getStringValue() {
135        return stringDataItem.getStringValue();
136    }
137
138    /**
139     * Get the <code>String</code> value that the given <code>StringIdItem</code> represents
140     * @param stringIdItem The <code>StringIdItem</code> to get the string value of
141     * @return the <code>String</code> value that the given <code>StringIdItem</code> represents
142     */
143    @Nullable
144    public static String getStringValue(@Nullable StringIdItem stringIdItem) {
145        return stringIdItem==null?null:stringIdItem.getStringValue();
146    }
147
148    /**
149     * Get the <code>StringDataItem</code> that this <code>StringIdItem</code> references
150     * @return the <code>StringDataItem</code> that this <code>StringIdItem</code> references
151     */
152    public StringDataItem getStringDataItem() {
153        return stringDataItem;
154    }
155
156    @Override
157    public int hashCode() {
158        return stringDataItem.hashCode();
159    }
160
161    @Override
162    public boolean equals(Object o) {
163        if (this==o) {
164            return true;
165        }
166        if (o==null || !this.getClass().equals(o.getClass())) {
167            return false;
168        }
169
170        //This assumes that the referenced items have been interned in both objects.
171        //This is a valid assumption because all outside code must use the static
172        //"getInterned..." style methods to make new items, and any item created
173        //internally is guaranteed to be interned
174        StringIdItem other = (StringIdItem)o;
175        return stringDataItem == other.stringDataItem;
176    }
177}
178