ReadContext.java revision 83b80f81d311b233188c281059aad4a9f5e8b4e6
183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com/*
283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * [The "BSD licence"]
383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * Copyright (c) 2009 Ben Gruver
483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * All rights reserved.
583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *
683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * Redistribution and use in source and binary forms, with or without
783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * modification, are permitted provided that the following conditions
883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * are met:
983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 1. Redistributions of source code must retain the above copyright
1083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer.
1183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 2. Redistributions in binary form must reproduce the above copyright
1283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer in the
1383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    documentation and/or other materials provided with the distribution.
1483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 3. The name of the author may not be used to endorse or promote products
1583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    derived from this software without specific prior written permission.
1683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *
1783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com */
2883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
2983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.compackage org.jf.dexlib;
3083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
3183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.SparseArray;
3283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.comimport junit.framework.Assert;
3383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
3483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.comimport java.util.List;
3583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
3683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
3783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com/**
3883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * This class stores context information that is only needed when reading in a dex file
3983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * Namely, it handles "pre-creating" items when an item needs to resolve some other item
4083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * that it references, and keeps track of those pre-created items, so the corresponding section
4183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * for the pre-created items uses them, instead of creating new items
4283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com */
4383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.comclass ReadContext {
4483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private final DexFile dexFile;
4583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
4683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<TypeListItem> typeListItems = new SparseArray<TypeListItem>(0);
4783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<AnnotationSetRefList> annotationSetRefLists = new SparseArray<AnnotationSetRefList>(0);
4883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<AnnotationSetItem> annotationSetItems = new SparseArray<AnnotationSetItem>(0);
4983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<ClassDataItem> classDataItems = new SparseArray<ClassDataItem>(0);
5083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<CodeItem> codeItems = new SparseArray<CodeItem>(0);
5183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<StringDataItem> stringDataItems = new SparseArray<StringDataItem>(0);
5283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<DebugInfoItem> debugInfoItems = new SparseArray<DebugInfoItem>(0);
5383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<AnnotationItem> annotationItems = new SparseArray<AnnotationItem>(0);
5483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<EncodedArrayItem> encodedArrayItems = new SparseArray<EncodedArrayItem>();
5583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray<AnnotationDirectoryItem> annotationDirectoryItems = new SparseArray<AnnotationDirectoryItem>();
5683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
5783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private SparseArray[] itemsByType = new SparseArray[] {
5883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //string_id_item
5983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //type_id_item
6083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //proto_id_item
6183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //field_id_item
6283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //method_id_item
6383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //class_def_item
6483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            typeListItems,
6583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            annotationSetRefLists,
6683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            annotationSetItems,
6783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            classDataItems,
6883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            codeItems,
6983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            stringDataItems,
7083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            debugInfoItems,
7183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            annotationItems,
7283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            encodedArrayItems,
7383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            annotationDirectoryItems,
7483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null, //map_list
7583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            null //header_item
7683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    };
7783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
7883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
7983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
8083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * The section sizes that are passed in while reading HeaderItem/MapItem, via the
8183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * addSection method.
8283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
8383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private int[] sectionSizes = new int[18];
8483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
8583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
8683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * The section offsets that are passed in while reading MapItem/HeaderItem, via the
8783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * addSection method.
8883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
8983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    private int[] sectionOffsets = new int[18];
9083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
9183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
9283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Creates a new ReadContext instance.
9383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param dexFile The dex file that is being read in
9483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
9583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public ReadContext(DexFile dexFile) {
9683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        this.dexFile = dexFile;
9783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
9883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        for (int i=0; i<18; i++) {
9983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sectionSizes[i] = -1;
10083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sectionOffsets[i] = -1;
10183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
10283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
10383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
10483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
10583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Returns a SparseArray containing the items of the given type
10683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * that have been pre-created while reading in other sections.
10783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     *
10883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * If the given ItemType isn't an offsetted item, this method will
10983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * return null
11083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType The type of item to get
11183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @return a SparseArray containing the items of the given type
11283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * that have been pre-created while reading in other sections, or
11383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * null if the ItemType isn't an offsetted item
11483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
11583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public SparseArray getItemsByType(ItemType itemType) {
11683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        return itemsByType[itemType.SectionIndex];
11783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
11883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
11983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
12083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Gets or creates an offsetted item of the specified type for the
12183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * given offset. Multiple calls to this method with the same itemType
12283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * and offset will return the same item.
12383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     *
12483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * It should not be assumed that the item that is returned will be
12583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * initialized. It is only guaranteed that the item will be read in
12683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * and initiliazed after the entire dex file has been read in.
12783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     *
12883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Note that it *is* guaranteed that this exact item will be added to
12983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * its corresponding section and read in. In other words, when the
13083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * corresponding section is being read in, it will use any items for
13183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * that have been "pre-created" by this method, and only create
13283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * new items for offsets that haven't been pre-created yet.
13383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     *
13483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType The type of item to get
13583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param offset The offset of the StringDataItem
13683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @return a StringDataItem for the given offset
13783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
13883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public Item getOffsettedItemByOffset(ItemType itemType, int offset) {
13983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        assert !itemType.isIndexedItem();
14083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
14183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        if (offset == 0) {
14283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            return null;
14383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
14483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
14583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        SparseArray<Item> sa = itemsByType[itemType.SectionIndex];
14683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        Item item = sa.get(offset);
14783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        if (item == null) {
14883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            item = ItemFactory.makeItem(itemType, dexFile);
14983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sa.put(offset, item);
15083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
15183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        return item;
15283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
15383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
15483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
15583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Adds the size and offset information for the given offset
15683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType the item type of the section
15783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param sectionSize the size of the section
15883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param sectionOffset the offset of the section
15983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
16083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public void addSection(final ItemType itemType, int sectionSize, int sectionOffset) {
16183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        if (!itemType.isIndexedItem()) {
16283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            itemsByType[itemType.SectionIndex].ensureCapacity(sectionSize);
16383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
16483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        int storedSectionSize = sectionSizes[itemType.SectionIndex];
16583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        if (storedSectionSize == -1) {
16683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sectionSizes[itemType.SectionIndex] = sectionSize;
16783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        } else {
16883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            if (storedSectionSize  != sectionSize) {
16983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                throw new RuntimeException("The section size in the header and map for item type "
17083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        + itemType + " do not match");
17183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            }
17283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
17383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
17483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        int storedSectionOffset = sectionOffsets[itemType.SectionIndex];
17583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        if (storedSectionOffset == -1) {
17683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sectionOffsets[itemType.SectionIndex] = sectionOffset;
17783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        } else {
17883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            if (storedSectionOffset != sectionOffset) {
17983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                throw new RuntimeException("The section offset in the header and map for item type "
18083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        + itemType + " do not match");
18183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            }
18283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
18383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
18483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
18583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
18683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
18783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * Sets the items for the specified section. This should be called by an offsetted section
18883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * after it is finished reading in all its items.
18983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType the item type of the section. This must be an offsetted item type
19083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param items the full list of items in the section, ordered by offset
19183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
19283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public void setItemsForSection(ItemType itemType, List<? extends Item> items) {
19383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        assert !itemType.isIndexedItem();
19483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
19583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        SparseArray<Item> sa = itemsByType[itemType.SectionIndex];
19683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
19783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        sa.clear();
19883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        sa.ensureCapacity(items.size());
19983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        for (Item item: items) {
20083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            sa.append(item.getOffset(), item);
20183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
20283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
20383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
20483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
20583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType the item type of the section
20683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @return the size of the given section as it was read in from the map item
20783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
20883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public int getSectionSize(ItemType itemType) {
20983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        return sectionSizes[itemType.SectionIndex];
21083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
21183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
21283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    /**
21383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @param itemType the item type of the section
21483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     * @return the offset of the given section as it was read in from the map item
21583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com     */
21683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public int getSectionOffset(ItemType itemType) {
21783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        return sectionOffsets[itemType.SectionIndex];
21883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
21983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com}
220