2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.dx.dex.file;
19 import com.android.dx.util.AnnotatedOutput;
20 import com.android.dx.util.Hex;
21 import java.util.List;
24 * Class that represents a contiguous list of uniform items. Each
25 * item in the list, in particular, must have the same write size and
28 * <p>This class inherits its alignment from its items, bumped up to
29 * {@code 4} if the items have a looser alignment requirement. If
30 * it is more than {@code 4}, then there will be a gap after the
31 * output list size (which is four bytes) and before the first item.</p>
33 * @param <T> type of element contained in an instance
35 public final class UniformListItem<T extends OffsettedItem>
36 extends OffsettedItem {
37 /** the size of the list header */
38 private static final int HEADER_SIZE = 4;
40 /** {@code non-null;} the item type */
41 private final ItemType itemType;
43 /** {@code non-null;} the contents */
44 private final List<T> items;
47 * Constructs an instance. It is illegal to modify the given list once
48 * it is used to construct an instance of this class.
50 * @param itemType {@code non-null;} the type of the item
51 * @param items {@code non-null and non-empty;} list of items to represent
53 public UniformListItem(ItemType itemType, List<T> items) {
54 super(getAlignment(items), writeSize(items));
56 if (itemType == null) {
57 throw new NullPointerException("itemType == null");
61 this.itemType = itemType;
65 * Helper for {@link #UniformListItem}, which returns the alignment
66 * requirement implied by the given list. See the header comment for
69 * @param items {@code non-null;} list of items being represented
70 * @return {@code >= 4;} the alignment requirement
72 private static int getAlignment(List<? extends OffsettedItem> items) {
74 // Since they all must have the same alignment, any one will do.
75 return Math.max(HEADER_SIZE, items.get(0).getAlignment());
76 } catch (IndexOutOfBoundsException ex) {
77 // Translate the exception.
78 throw new IllegalArgumentException("items.size() == 0");
79 } catch (NullPointerException ex) {
80 // Translate the exception.
81 throw new NullPointerException("items == null");
86 * Calculates the write size for the given list.
88 * @param items {@code non-null;} the list in question
89 * @return {@code >= 0;} the write size
91 private static int writeSize(List<? extends OffsettedItem> items) {
93 * This class assumes all included items are the same size,
94 * an assumption which is verified in place0().
96 OffsettedItem first = items.get(0);
97 return (items.size() * first.writeSize()) + getAlignment(items);
102 public ItemType itemType() {
108 public String toString() {
109 StringBuffer sb = new StringBuffer(100);
111 sb.append(getClass().getName());
114 return sb.toString();
119 public void addContents(DexFile file) {
120 for (OffsettedItem i : items) {
127 public final String toHuman() {
128 StringBuffer sb = new StringBuffer(100);
129 boolean first = true;
133 for (OffsettedItem i : items) {
139 sb.append(i.toHuman());
143 return sb.toString();
147 * Gets the underlying list of items.
149 * @return {@code non-null;} the list
151 public final List<T> getItems() {
157 protected void place0(Section addedTo, int offset) {
158 offset += headerSize();
160 boolean first = true;
162 int theAlignment = -1;
164 for (OffsettedItem i : items) {
165 int size = i.writeSize();
168 theAlignment = i.getAlignment();
171 if (size != theSize) {
172 throw new UnsupportedOperationException(
173 "item size mismatch");
175 if (i.getAlignment() != theAlignment) {
176 throw new UnsupportedOperationException(
177 "item alignment mismatch");
181 offset = i.place(addedTo, offset) + size;
187 protected void writeTo0(DexFile file, AnnotatedOutput out) {
188 int size = items.size();
190 if (out.annotates()) {
191 out.annotate(0, offsetString() + " " + typeName());
192 out.annotate(4, " size: " + Hex.u4(size));
197 for (OffsettedItem i : items) {
198 i.writeTo(file, out);
203 * Get the size of the header of this list.
205 * @return {@code >= 0;} the header size
207 private int headerSize() {
209 * Because of how this instance was set up, this is the same
212 return getAlignment();