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.Hex; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Class that represents a contiguous list of uniform items. Each 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * item in the list, in particular, must have the same write size and 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * alignment. 27de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>This class inherits its alignment from its items, bumped up to 2999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code 4} if the items have a looser alignment requirement. If 3099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * it is more than {@code 4}, then there will be a gap after the 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * output list size (which is four bytes) and before the first item.</p> 32de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param <T> type of element contained in an instance 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class UniformListItem<T extends OffsettedItem> 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extends OffsettedItem { 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** the size of the list header */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int HEADER_SIZE = 4; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the item type */ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ItemType itemType; 42de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the contents */ 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final List<T> items; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. It is illegal to modify the given list once 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it is used to construct an instance of this class. 49de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param itemType {@code non-null;} the type of the item 5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param items {@code non-null and non-empty;} list of items to represent 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public UniformListItem(ItemType itemType, List<T> items) { 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(getAlignment(items), writeSize(items)); 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (itemType == null) { 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("itemType == null"); 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.items = items; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.itemType = itemType; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for {@link #UniformListItem}, which returns the alignment 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * requirement implied by the given list. See the header comment for 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * more details. 68de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param items {@code non-null;} list of items being represented 7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 4;} the alignment requirement 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static int getAlignment(List<? extends OffsettedItem> items) { 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Since they all must have the same alignment, any one will do. 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return Math.max(HEADER_SIZE, items.get(0).getAlignment()); 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IndexOutOfBoundsException ex) { 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Translate the exception. 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("items.size() == 0"); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (NullPointerException ex) { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Translate the exception. 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("items == null"); 82de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro } 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calculates the write size for the given list. 87de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 8899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param items {@code non-null;} the list in question 8999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0;} the write size 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static int writeSize(List<? extends OffsettedItem> items) { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class assumes all included items are the same size, 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an assumption which is verified in place0(). 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OffsettedItem first = items.get(0); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (items.size() * first.writeSize()) + getAlignment(items); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ItemType itemType() { 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return itemType; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuffer sb = new StringBuffer(100); 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(getClass().getName()); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(items); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return sb.toString(); 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void addContents(DexFile file) { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem i : items) { 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i.addContents(file); 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final String toHuman() { 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuffer sb = new StringBuffer(100); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean first = true; 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append("{"); 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem i : items) { 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (first) { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(", "); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(i.toHuman()); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append("}"); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return sb.toString(); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the underlying list of items. 148de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 14999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the list 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final List<T> getItems() { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return items; 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected void place0(Section addedTo, int offset) { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset += headerSize(); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean first = true; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int theSize = -1; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int theAlignment = -1; 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem i : items) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = i.writeSize(); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (first) { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project theSize = size; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project theAlignment = i.getAlignment(); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size != theSize) { 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new UnsupportedOperationException( 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "item size mismatch"); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (i.getAlignment() != theAlignment) { 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new UnsupportedOperationException( 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "item alignment mismatch"); 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 180de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset = i.place(addedTo, offset) + size; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected void writeTo0(DexFile file, AnnotatedOutput out) { 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = items.size(); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (out.annotates()) { 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(0, offsetString() + " " + typeName()); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(4, " size: " + Hex.u4(size)); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.writeInt(size); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (OffsettedItem i : items) { 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i.writeTo(file, out); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the size of the header of this list. 204de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 20599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 0;} the header size 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int headerSize() { 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because of how this instance was set up, this is the same 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as the alignment. 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return getAlignment(); 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 215