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;
33
34/**
35 * This item represents a map_list item from the dex specification. It contains a
36 * SectionInfo instance for every section in the DexFile, with the number of items
37 * in and offset of that section.
38 */
39public class MapItem extends Item<MapItem> {
40    /**
41     * This item is read in immediately after the HeaderItem, and the section info contained
42     * by this item is added to the ReadContext object, which is used when reading in the other
43     * sections in the dex file.
44     *
45     * This item should be placed last. It depends on the fact that the other sections
46     * in the file have been placed.
47     */
48
49    /**
50     * Create a new uninitialized <code>MapItem</code>
51     * @param dexFile The <code>DexFile</code> that this item belongs to
52     */
53    protected MapItem(final DexFile dexFile) {
54        super(dexFile);
55    }
56
57    /** {@inheritDoc} */
58    protected int placeItem(int offset) {
59        Section[] sections = dexFile.getOrderedSections();
60        //the list returned by getOrderedSections doesn't contain the header
61        //or map section, so add 2 to the length
62        return offset + 4 + (sections.length + 2) * 12;
63    }
64
65    /** {@inheritDoc} */
66    protected void readItem(Input in, ReadContext readContext) {
67        int size = in.readInt();
68
69        for (int i=0; i<size; i++) {
70            ItemType itemType = ItemType.fromInt(in.readShort());
71
72            //unused
73            in.readShort();
74
75            int sectionSize = in.readInt();
76            int sectionOffset = in.readInt();
77
78            readContext.addSection(itemType, sectionSize, sectionOffset);
79        }
80    }
81
82    /** {@inheritDoc} */
83    protected void writeItem(AnnotatedOutput out) {
84        assert getOffset() > 0;
85        Section[] sections = dexFile.getOrderedSections();
86
87        out.annotate("map_size: 0x" + Integer.toHexString(sections.length + 2) + " (" +
88                Integer.toString(sections.length + 2) + ")");
89        out.writeInt(sections.length + 2);
90
91        int index = 0;
92        out.annotate(0, "[" + index++ + "]");
93        out.indent();
94        writeSectionInfo(out, ItemType.TYPE_HEADER_ITEM, 1, 0);
95        out.deindent();
96
97        for (Section section: dexFile.getOrderedSections()) {
98            out.annotate(0, "[" + index++ + "]");
99            out.indent();
100            writeSectionInfo(out, section.ItemType, section.getItems().size(), section.getOffset());
101            out.deindent();
102        }
103
104        out.annotate(0, "[" + index++ + "]");
105        out.indent();
106        writeSectionInfo(out, ItemType.TYPE_MAP_LIST, 1, dexFile.MapItem.getOffset());
107        out.deindent();
108    }
109
110    private void writeSectionInfo(AnnotatedOutput out, ItemType itemType, int sectionSize, int sectionOffset) {
111        if (out.annotates()) {
112            out.annotate(2, "item_type: " + itemType);
113            out.annotate(2, "unused");
114            out.annotate(4, "section_size: 0x" + Integer.toHexString(sectionSize) + " (" + sectionSize + ")");
115            out.annotate(4, "section_off: 0x" + Integer.toHexString(sectionOffset));
116        }
117
118        out.writeShort(itemType.MapValue);
119        out.writeShort(0);
120        out.writeInt(sectionSize);
121        out.writeInt(sectionOffset);
122    }
123
124    /** {@inheritDoc} */
125    public ItemType getItemType() {
126        return ItemType.TYPE_MAP_LIST;
127    }
128
129    /** {@inheritDoc} */
130    public int compareTo(MapItem o) {
131        return 0;
132    }
133
134    /** {@inheritDoc} */
135    public String getConciseIdentity() {
136        return "map_item";
137    }
138}
139