summaryrefslogtreecommitdiff
path: root/dexgen/src/com/android/dexgen/dex/file/MapItem.java
diff options
context:
space:
mode:
Diffstat (limited to 'dexgen/src/com/android/dexgen/dex/file/MapItem.java')
-rw-r--r--dexgen/src/com/android/dexgen/dex/file/MapItem.java235
1 files changed, 235 insertions, 0 deletions
diff --git a/dexgen/src/com/android/dexgen/dex/file/MapItem.java b/dexgen/src/com/android/dexgen/dex/file/MapItem.java
new file mode 100644
index 0000000..02472d4
--- /dev/null
+++ b/dexgen/src/com/android/dexgen/dex/file/MapItem.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2008 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.dexgen.dex.file;
+
+import com.android.dexgen.util.AnnotatedOutput;
+import com.android.dexgen.util.Hex;
+
+import java.util.ArrayList;
+
+/**
+ * Class that represents a map item.
+ */
+public final class MapItem extends OffsettedItem {
+ /** file alignment of this class, in bytes */
+ private static final int ALIGNMENT = 4;
+
+ /** write size of this class, in bytes: three {@code uint}s */
+ private static final int WRITE_SIZE = (4 * 3);
+
+ /** {@code non-null;} item type this instance covers */
+ private final ItemType type;
+
+ /** {@code non-null;} section this instance covers */
+ private final Section section;
+
+ /**
+ * {@code null-ok;} first item covered or {@code null} if this is
+ * a self-reference
+ */
+ private final Item firstItem;
+
+ /**
+ * {@code null-ok;} last item covered or {@code null} if this is
+ * a self-reference
+ */
+ private final Item lastItem;
+
+ /**
+ * {@code > 0;} count of items covered; {@code 1} if this
+ * is a self-reference
+ */
+ private final int itemCount;
+
+ /**
+ * Constructs a list item with instances of this class representing
+ * the contents of the given array of sections, adding it to the
+ * given map section.
+ *
+ * @param sections {@code non-null;} the sections
+ * @param mapSection {@code non-null;} the section that the resulting map
+ * should be added to; it should be empty on entry to this method
+ */
+ public static void addMap(Section[] sections,
+ MixedItemSection mapSection) {
+ if (sections == null) {
+ throw new NullPointerException("sections == null");
+ }
+
+ if (mapSection.items().size() != 0) {
+ throw new IllegalArgumentException(
+ "mapSection.items().size() != 0");
+ }
+
+ ArrayList<MapItem> items = new ArrayList<MapItem>(50);
+
+ for (Section section : sections) {
+ ItemType currentType = null;
+ Item firstItem = null;
+ Item lastItem = null;
+ int count = 0;
+
+ for (Item item : section.items()) {
+ ItemType type = item.itemType();
+ if (type != currentType) {
+ if (count != 0) {
+ items.add(new MapItem(currentType, section,
+ firstItem, lastItem, count));
+ }
+ currentType = type;
+ firstItem = item;
+ count = 0;
+ }
+ lastItem = item;
+ count++;
+ }
+
+ if (count != 0) {
+ // Add a MapItem for the final items in the section.
+ items.add(new MapItem(currentType, section,
+ firstItem, lastItem, count));
+ } else if (section == mapSection) {
+ // Add a MapItem for the self-referential section.
+ items.add(new MapItem(mapSection));
+ }
+ }
+
+ mapSection.add(
+ new UniformListItem<MapItem>(ItemType.TYPE_MAP_LIST, items));
+ }
+
+ /**
+ * Constructs an instance.
+ *
+ * @param type {@code non-null;} item type this instance covers
+ * @param section {@code non-null;} section this instance covers
+ * @param firstItem {@code non-null;} first item covered
+ * @param lastItem {@code non-null;} last item covered
+ * @param itemCount {@code > 0;} count of items covered
+ */
+ private MapItem(ItemType type, Section section, Item firstItem,
+ Item lastItem, int itemCount) {
+ super(ALIGNMENT, WRITE_SIZE);
+
+ if (type == null) {
+ throw new NullPointerException("type == null");
+ }
+
+ if (section == null) {
+ throw new NullPointerException("section == null");
+ }
+
+ if (firstItem == null) {
+ throw new NullPointerException("firstItem == null");
+ }
+
+ if (lastItem == null) {
+ throw new NullPointerException("lastItem == null");
+ }
+
+ if (itemCount <= 0) {
+ throw new IllegalArgumentException("itemCount <= 0");
+ }
+
+ this.type = type;
+ this.section = section;
+ this.firstItem = firstItem;
+ this.lastItem = lastItem;
+ this.itemCount = itemCount;
+ }
+
+ /**
+ * Constructs a self-referential instance. This instance is meant to
+ * represent the section containing the {@code map_list}.
+ *
+ * @param section {@code non-null;} section this instance covers
+ */
+ private MapItem(Section section) {
+ super(ALIGNMENT, WRITE_SIZE);
+
+ if (section == null) {
+ throw new NullPointerException("section == null");
+ }
+
+ this.type = ItemType.TYPE_MAP_LIST;
+ this.section = section;
+ this.firstItem = null;
+ this.lastItem = null;
+ this.itemCount = 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ItemType itemType() {
+ return ItemType.TYPE_MAP_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer(100);
+
+ sb.append(getClass().getName());
+ sb.append('{');
+ sb.append(section.toString());
+ sb.append(' ');
+ sb.append(type.toHuman());
+ sb.append('}');
+
+ return sb.toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addContents(DexFile file) {
+ // We have nothing to add.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String toHuman() {
+ return toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void writeTo0(DexFile file, AnnotatedOutput out) {
+ int value = type.getMapValue();
+ int offset;
+
+ if (firstItem == null) {
+ offset = section.getFileOffset();
+ } else {
+ offset = section.getAbsoluteItemOffset(firstItem);
+ }
+
+ if (out.annotates()) {
+ out.annotate(0, offsetString() + ' ' + type.getTypeName() +
+ " map");
+ out.annotate(2, " type: " + Hex.u2(value) + " // " +
+ type.toString());
+ out.annotate(2, " unused: 0");
+ out.annotate(4, " size: " + Hex.u4(itemCount));
+ out.annotate(4, " offset: " + Hex.u4(offset));
+ }
+
+ out.writeShort(value);
+ out.writeShort(0); // unused
+ out.writeInt(itemCount);
+ out.writeInt(offset);
+ }
+}