1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17package com.android.dx.dex.file; 18 19import com.android.dx.rop.cst.Constant; 20import com.android.dx.rop.type.Prototype; 21import com.android.dx.util.AnnotatedOutput; 22import com.android.dx.util.Hex; 23 24import java.util.Collection; 25import java.util.TreeMap; 26 27/** 28 * Proto (method prototype) identifiers list section of a 29 * {@code .dex} file. 30 */ 31public final class ProtoIdsSection extends UniformItemSection { 32 /** 33 * {@code non-null;} map from method prototypes to {@link ProtoIdItem} instances 34 */ 35 private final TreeMap<Prototype, ProtoIdItem> protoIds; 36 37 /** 38 * Constructs an instance. The file offset is initially unknown. 39 * 40 * @param file {@code non-null;} file that this instance is part of 41 */ 42 public ProtoIdsSection(DexFile file) { 43 super("proto_ids", file, 4); 44 45 protoIds = new TreeMap<Prototype, ProtoIdItem>(); 46 } 47 48 /** {@inheritDoc} */ 49 @Override 50 public Collection<? extends Item> items() { 51 return protoIds.values(); 52 } 53 54 /** {@inheritDoc} */ 55 @Override 56 public IndexedItem get(Constant cst) { 57 throw new UnsupportedOperationException("unsupported"); 58 } 59 60 /** 61 * Writes the portion of the file header that refers to this instance. 62 * 63 * @param out {@code non-null;} where to write 64 */ 65 public void writeHeaderPart(AnnotatedOutput out) { 66 throwIfNotPrepared(); 67 68 int sz = protoIds.size(); 69 int offset = (sz == 0) ? 0 : getFileOffset(); 70 71 if (sz > 65536) { 72 throw new UnsupportedOperationException("too many proto ids"); 73 } 74 75 if (out.annotates()) { 76 out.annotate(4, "proto_ids_size: " + Hex.u4(sz)); 77 out.annotate(4, "proto_ids_off: " + Hex.u4(offset)); 78 } 79 80 out.writeInt(sz); 81 out.writeInt(offset); 82 } 83 84 /** 85 * Interns an element into this instance. 86 * 87 * @param prototype {@code non-null;} the prototype to intern 88 * @return {@code non-null;} the interned reference 89 */ 90 public ProtoIdItem intern(Prototype prototype) { 91 if (prototype == null) { 92 throw new NullPointerException("prototype == null"); 93 } 94 95 throwIfPrepared(); 96 97 ProtoIdItem result = protoIds.get(prototype); 98 99 if (result == null) { 100 result = new ProtoIdItem(prototype); 101 protoIds.put(prototype, result); 102 } 103 104 return result; 105 } 106 107 /** 108 * Gets the index of the given prototype, which must have 109 * been added to this instance. 110 * 111 * @param prototype {@code non-null;} the prototype to look up 112 * @return {@code >= 0;} the reference's index 113 */ 114 public int indexOf(Prototype prototype) { 115 if (prototype == null) { 116 throw new NullPointerException("prototype == null"); 117 } 118 119 throwIfNotPrepared(); 120 121 ProtoIdItem item = protoIds.get(prototype); 122 123 if (item == null) { 124 throw new IllegalArgumentException("not found"); 125 } 126 127 return item.getIndex(); 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 protected void orderItems() { 133 int idx = 0; 134 135 for (Object i : items()) { 136 ((ProtoIdItem) i).setIndex(idx); 137 idx++; 138 } 139 } 140} 141