15867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com/*
25867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * [The "BSD licence"]
300fc68adf2e39aeb9fed35293f2576bbe729ec4bJesusFreke@JesusFreke.com * Copyright (c) 2010 Ben Gruver (JesusFreke)
45867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * All rights reserved.
55867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
65867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * Redistribution and use in source and binary forms, with or without
75867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * modification, are permitted provided that the following conditions
85867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * are met:
95867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * 1. Redistributions of source code must retain the above copyright
105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer.
115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * 2. Redistributions in binary form must reproduce the above copyright
125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer in the
135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *    documentation and/or other materials provided with the distribution.
145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * 3. The name of the author may not be used to endorse or promote products
155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *    derived from this software without specific prior written permission.
165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com */
285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compackage org.jf.dexlib;
305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.AnnotatedOutput;
32b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.Input;
33b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.Utf8Utils;
345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
3558e4b792b8c6103416808c13eedd926cff118c80Ben Gruverimport javax.annotation.Nullable;
3658e4b792b8c6103416808c13eedd926cff118c80Ben Gruver
375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compublic class StringIdItem extends Item<StringIdItem> {
385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private StringDataItem stringDataItem;
395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com   /**
415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Creates a new uninitialized <code>StringIdItem</code>
425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param dexFile The <code>DexFile</code> that this item belongs to
435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    protected StringIdItem(DexFile dexFile) {
455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        super(dexFile);
465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Creates a new <code>StringIdItem</code> for the given <code>StringDataItem</code>
505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param dexFile The <code>DexFile</code> that this item belongs to
515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param stringDataItem The <code>StringDataItem</code> that this <code>StringIdItem</code> represents
525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        super(dexFile);
555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.stringDataItem = stringDataItem;
565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Returns a <code>StringIdItem</code> for the given values, and that has been interned into
605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * the given <code>DexFile</code>
615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param dexFile The <code>DexFile</code> that this item will belong to
625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param stringValue The string value that this item represents
635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @return a <code>StringIdItem</code> for the given values, and that has been interned into
645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * the given <code>DexFile</code>
655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
66928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com    public static StringIdItem internStringIdItem(DexFile dexFile, String stringValue) {
67928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        StringDataItem stringDataItem = StringDataItem.internStringDataItem(dexFile, stringValue);
685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (stringDataItem == null) {
695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return null;
705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return dexFile.StringIdsSection.intern(stringIdItem);
735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
75928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com    /**
76928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * Looks up the <code>StringIdItem</code> from the given <code>DexFile</code> for the given
77928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * string value
78928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * @param dexFile the <code>Dexfile</code> to find the string value in
79928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * @param stringValue The string value to look up
80928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * @return a <code>StringIdItem</code> from the given <code>DexFile</code> for the given
81928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     * string value, or null if it doesn't exist
82928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com     */
83928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com    public static StringIdItem lookupStringIdItem(DexFile dexFile, String stringValue) {
84928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        StringDataItem stringDataItem = StringDataItem.lookupStringDataItem(dexFile, stringValue);
85928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        if (stringDataItem == null) {
86928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com            return null;
87928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        }
88928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
89928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com        return dexFile.StringIdsSection.getInternedItem(stringIdItem);
90928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com    }
91928790f2939e0eec7ab2e4653a19c6c27a113634JesusFreke@JesusFreke.com
925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    protected void readItem(Input in, ReadContext readContext) {
945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int stringDataOffset = in.readInt();
955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
965867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        stringDataItem = (StringDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_STRING_DATA_ITEM,
975867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                stringDataOffset);
985867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
995867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    protected int placeItem(int offset) {
1025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return offset + 4;
1035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1045867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    protected void writeItem(AnnotatedOutput out) {
1075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (out.annotates()) {
1085867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            out.annotate(4, stringDataItem.getConciseIdentity());
1095867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        out.writeInt(stringDataItem.getOffset());
1125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public ItemType getItemType() {
1165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return ItemType.TYPE_STRING_ID_ITEM;
1175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public String getConciseIdentity() {
1215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return "string_id_item: " + Utf8Utils.escapeString(getStringValue());
1225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int compareTo(StringIdItem o) {
1265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //sort by the string value
1275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return getStringValue().compareTo(o.getStringValue());
1285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
1315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Get the <code>String</code> value that this <code>StringIdItem</code> represents
1325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @return the <code>String</code> value that this <code>StringIdItem</code> represents
1335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
1345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public String getStringValue() {
1355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return stringDataItem.getStringValue();
13658e4b792b8c6103416808c13eedd926cff118c80Ben Gruver    }
13758e4b792b8c6103416808c13eedd926cff118c80Ben Gruver
13858e4b792b8c6103416808c13eedd926cff118c80Ben Gruver    /**
13958e4b792b8c6103416808c13eedd926cff118c80Ben Gruver     * Get the <code>String</code> value that the given <code>StringIdItem</code> represents
14058e4b792b8c6103416808c13eedd926cff118c80Ben Gruver     * @param stringIdItem The <code>StringIdItem</code> to get the string value of
14158e4b792b8c6103416808c13eedd926cff118c80Ben Gruver     * @return the <code>String</code> value that the given <code>StringIdItem</code> represents
14258e4b792b8c6103416808c13eedd926cff118c80Ben Gruver     */
14358e4b792b8c6103416808c13eedd926cff118c80Ben Gruver    @Nullable
14458e4b792b8c6103416808c13eedd926cff118c80Ben Gruver    public static String getStringValue(@Nullable StringIdItem stringIdItem) {
14558e4b792b8c6103416808c13eedd926cff118c80Ben Gruver        return stringIdItem==null?null:stringIdItem.getStringValue();
1465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
1495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Get the <code>StringDataItem</code> that this <code>StringIdItem</code> references
1505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @return the <code>StringDataItem</code> that this <code>StringIdItem</code> references
1515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
1525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public StringDataItem getStringDataItem() {
1535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return stringDataItem;
1545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    @Override
1575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int hashCode() {
1585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return stringDataItem.hashCode();
1595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    @Override
1625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public boolean equals(Object o) {
1635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (this==o) {
1645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return true;
1655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (o==null || !this.getClass().equals(o.getClass())) {
1675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return false;
1685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //This assumes that the referenced items have been interned in both objects.
1715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //This is a valid assumption because all outside code must use the static
1725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //"getInterned..." style methods to make new items, and any item created
1735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //internally is guaranteed to be interned
1745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        StringIdItem other = (StringIdItem)o;
1755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return stringDataItem == other.stringDataItem;
1765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com}
178