com.android.dx.dex.file.UniformListItem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.dex.file;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
import java.util.List;
/**
* Class that represents a contiguous list of uniform items. Each
* item in the list, in particular, must have the same write size and
* alignment.
*
* This class inherits its alignment from its items, bumped up to
* {@code 4} if the items have a looser alignment requirement. If
* it is more than {@code 4}, then there will be a gap after the
* output list size (which is four bytes) and before the first item.
*
* @param type of element contained in an instance
*/
public final class UniformListItem
extends OffsettedItem {
/** the size of the list header */
private static final int HEADER_SIZE = 4;
/** {@code non-null;} the item type */
private final ItemType itemType;
/** {@code non-null;} the contents */
private final List items;
/**
* Constructs an instance. It is illegal to modify the given list once
* it is used to construct an instance of this class.
*
* @param itemType {@code non-null;} the type of the item
* @param items {@code non-null and non-empty;} list of items to represent
*/
public UniformListItem(ItemType itemType, List items) {
super(getAlignment(items), writeSize(items));
if (itemType == null) {
throw new NullPointerException("itemType == null");
}
this.items = items;
this.itemType = itemType;
}
/**
* Helper for {@link #UniformListItem}, which returns the alignment
* requirement implied by the given list. See the header comment for
* more details.
*
* @param items {@code non-null;} list of items being represented
* @return {@code >= 4;} the alignment requirement
*/
private static int getAlignment(List extends OffsettedItem> items) {
try {
// Since they all must have the same alignment, any one will do.
return Math.max(HEADER_SIZE, items.get(0).getAlignment());
} catch (IndexOutOfBoundsException ex) {
// Translate the exception.
throw new IllegalArgumentException("items.size() == 0");
} catch (NullPointerException ex) {
// Translate the exception.
throw new NullPointerException("items == null");
}
}
/**
* Calculates the write size for the given list.
*
* @param items {@code non-null;} the list in question
* @return {@code >= 0;} the write size
*/
private static int writeSize(List extends OffsettedItem> items) {
/*
* This class assumes all included items are the same size,
* an assumption which is verified in place0().
*/
OffsettedItem first = items.get(0);
return (items.size() * first.writeSize()) + getAlignment(items);
}
/** {@inheritDoc} */
@Override
public ItemType itemType() {
return itemType;
}
/** {@inheritDoc} */
@Override
public String toString() {
StringBuffer sb = new StringBuffer(100);
sb.append(getClass().getName());
sb.append(items);
return sb.toString();
}
/** {@inheritDoc} */
@Override
public void addContents(DexFile file) {
for (OffsettedItem i : items) {
i.addContents(file);
}
}
/** {@inheritDoc} */
@Override
public final String toHuman() {
StringBuffer sb = new StringBuffer(100);
boolean first = true;
sb.append("{");
for (OffsettedItem i : items) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(i.toHuman());
}
sb.append("}");
return sb.toString();
}
/**
* Gets the underlying list of items.
*
* @return {@code non-null;} the list
*/
public final List getItems() {
return items;
}
/** {@inheritDoc} */
@Override
protected void place0(Section addedTo, int offset) {
offset += headerSize();
boolean first = true;
int theSize = -1;
int theAlignment = -1;
for (OffsettedItem i : items) {
int size = i.writeSize();
if (first) {
theSize = size;
theAlignment = i.getAlignment();
first = false;
} else {
if (size != theSize) {
throw new UnsupportedOperationException(
"item size mismatch");
}
if (i.getAlignment() != theAlignment) {
throw new UnsupportedOperationException(
"item alignment mismatch");
}
}
offset = i.place(addedTo, offset) + size;
}
}
/** {@inheritDoc} */
@Override
protected void writeTo0(DexFile file, AnnotatedOutput out) {
int size = items.size();
if (out.annotates()) {
out.annotate(0, offsetString() + " " + typeName());
out.annotate(4, " size: " + Hex.u4(size));
}
out.writeInt(size);
for (OffsettedItem i : items) {
i.writeTo(file, out);
}
}
/**
* Get the size of the header of this list.
*
* @return {@code >= 0;} the header size
*/
private int headerSize() {
/*
* Because of how this instance was set up, this is the same
* as the alignment.
*/
return getAlignment();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy