1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.file; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Collection; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Collections; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Comparator; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.HashMap; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Map; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.NoSuchElementException; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.TreeMap; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 3499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * A section of a {@code .dex} file which consists of a sequence of 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@link OffsettedItem} objects, which may each be of a different concrete 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class and/or size. 37de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <b>Note:</b> It is invalid for an item in an instance of this class to 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have a larger alignment requirement than the alignment of this instance. 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class MixedItemSection extends Section { 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project static enum SortType { 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** no sorting */ 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project NONE, 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** sort by type only */ 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TYPE, 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** sort in class-major order, with instances sorted per-class */ 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project INSTANCE; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} sorter which sorts instances by type */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final Comparator<OffsettedItem> TYPE_SORTER = 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new Comparator<OffsettedItem>() { 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compare(OffsettedItem item1, OffsettedItem item2) { 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ItemType type1 = item1.itemType(); 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ItemType type2 = item2.itemType(); 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return type1.compareTo(type2); 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 62de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the items in this part */ 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ArrayList<OffsettedItem> items; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} items that have been explicitly interned */ 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final HashMap<OffsettedItem, OffsettedItem> interns; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} how to sort the items */ 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final SortType sort; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code >= -1;} the current size of this part, in bytes, or {@code -1} 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if not yet calculated 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int writeSize; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. The file offset is initially unknown. 80de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param name {@code null-ok;} the name of this instance, for annotation 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * purposes 8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param file {@code non-null;} file that this instance is part of 8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param alignment {@code > 0;} alignment requirement for the final output; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * must be a power of 2 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param sort how the items should be sorted in the final output 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public MixedItemSection(String name, DexFile file, int alignment, 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SortType sort) { 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(name, file, alignment); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.items = new ArrayList<OffsettedItem>(100); 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.interns = new HashMap<OffsettedItem, OffsettedItem>(100); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.sort = sort; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.writeSize = -1; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Collection<? extends Item> items() { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return items; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int writeSize() { 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfNotPrepared(); 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return writeSize; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getAbsoluteItemOffset(Item item) { 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem oi = (OffsettedItem) item; 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return oi.getAbsoluteOffset(); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the size of this instance, in items. 120de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 12199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0;} the size 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int size() { 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return items.size(); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Writes the portion of the file header that refers to this instance. 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} where to write 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeHeaderPart(AnnotatedOutput out) { 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfNotPrepared(); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (writeSize == -1) { 136de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro throw new RuntimeException("write size not yet set"); 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = writeSize; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = (sz == 0) ? 0 : getFileOffset(); 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String name = getName(); 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (name == null) { 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project name = "<unnamed>"; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int spaceCount = 15 - name.length(); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char[] spaceArr = new char[spaceCount]; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Arrays.fill(spaceArr, ' '); 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String spaces = new String(spaceArr); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (out.annotates()) { 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(4, name + "_size:" + spaces + Hex.u4(sz)); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(4, name + "_off: " + spaces + Hex.u4(offset)); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.writeInt(sz); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.writeInt(offset); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Adds an item to this instance. This will in turn tell the given item 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that it has been added to this instance. It is invalid to add the 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same item to more than one instance, nor to add the same items 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * multiple times to a single instance. 166de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 16799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param item {@code non-null;} the item to add 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void add(OffsettedItem item) { 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfPrepared(); 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (item.getAlignment() > getAlignment()) { 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException( 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "incompatible item alignment"); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (NullPointerException ex) { 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Elucidate the exception. 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("item == null"); 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project items.add(item); 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Interns an item in this instance, returning the interned instance 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (which may not be the one passed in). This will add the item if no 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * equal item has been added. 189de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 19099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param item {@code non-null;} the item to intern 19199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the equivalent interned instance 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public <T extends OffsettedItem> T intern(T item) { 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfPrepared(); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem result = interns.get(item); 197de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result != null) { 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (T) result; 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add(item); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project interns.put(item, item); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return item; 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets an item which was previously interned. 209de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 21099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param item {@code non-null;} the item to look for 21199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the equivalent already-interned instance 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public <T extends OffsettedItem> T get(T item) { 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfNotPrepared(); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem result = interns.get(item); 217de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result != null) { 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (T) result; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NoSuchElementException(item.toString()); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Writes an index of contents of the items in this instance of the 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * given type. If there are none, this writes nothing. If there are any, 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then the index is preceded by the given intro string. 229de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 23099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} where to write to 23199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param itemType {@code non-null;} the item type of interest 23299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param intro {@code non-null;} the introductory string for non-empty indices 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeIndexAnnotation(AnnotatedOutput out, ItemType itemType, 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String intro) { 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfNotPrepared(); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TreeMap<String, OffsettedItem> index = 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new TreeMap<String, OffsettedItem>(); 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem item : items) { 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (item.itemType() == itemType) { 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String label = item.toHuman(); 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project index.put(label, item); 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (index.size() == 0) { 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(0, intro); 253de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (Map.Entry<String, OffsettedItem> entry : index.entrySet()) { 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String label = entry.getKey(); 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem item = entry.getValue(); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(0, item.offsetString() + ' ' + label + '\n'); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected void prepare0() { 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile file = getFile(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's okay for new items to be added as a result of an 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * addContents() call; we just have to deal with the possibility. 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i = 0; 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (;;) { 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = items.size(); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (i >= sz) { 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (/*i*/; i < sz; i++) { 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem one = items.get(i); 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project one.addContents(file); 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Places all the items in this instance at particular offsets. This 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will call {@link OffsettedItem#place} on each item. If an item 28899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * does not know its write size before the call to {@code place}, 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it is that call which is responsible for setting the write size. 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This method may only be called once per instance; subsequent calls 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will throw an exception. 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void placeItems() { 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwIfNotPrepared(); 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (sort) { 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case INSTANCE: { 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Collections.sort(items); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case TYPE: { 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Collections.sort(items, TYPE_SORTER); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = items.size(); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int outAt = 0; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem one = items.get(i); 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int placedAt = one.place(this, outAt); 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (placedAt < outAt) { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("bogus place() result for " + 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project one); 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outAt = placedAt + one.writeSize(); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ExceptionWithContext.withContext(ex, 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "...while placing " + one); 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeSize = outAt; 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected void writeTo0(AnnotatedOutput out) { 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean annotates = out.annotates(); 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean first = true; 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile file = getFile(); 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = 0; 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem one : items) { 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotates) { 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (first) { 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(0, "\n"); 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int alignMask = one.getAlignment() - 1; 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = (at + alignMask) & ~alignMask; 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (at != writeAt) { 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.writeZeroes(writeAt - at); 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at = writeAt; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project one.writeTo(file, out); 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += one.writeSize(); 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (at != writeSize) { 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("output size mismatch"); 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 363