Home | History | Annotate | Download | only in file
      1 /*
      2  * Copyright (C) 2007 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 
     17 package com.android.dexgen.dex.file;
     18 
     19 import com.android.dexgen.rop.cst.Constant;
     20 import com.android.dexgen.rop.cst.CstType;
     21 import com.android.dexgen.rop.type.Type;
     22 import com.android.dexgen.util.AnnotatedOutput;
     23 import com.android.dexgen.util.Hex;
     24 
     25 import java.util.Collection;
     26 import java.util.TreeMap;
     27 
     28 /**
     29  * Type identifiers list section of a {@code .dex} file.
     30  */
     31 public final class TypeIdsSection extends UniformItemSection {
     32     /**
     33      * {@code non-null;} map from types to {@link TypeIdItem} instances
     34      */
     35     private final TreeMap<Type, TypeIdItem> typeIds;
     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 TypeIdsSection(DexFile file) {
     43         super("type_ids", file, 4);
     44 
     45         typeIds = new TreeMap<Type, TypeIdItem>();
     46     }
     47 
     48     /** {@inheritDoc} */
     49     @Override
     50     public Collection<? extends Item> items() {
     51         return typeIds.values();
     52     }
     53 
     54     /** {@inheritDoc} */
     55     @Override
     56     public IndexedItem get(Constant cst) {
     57         if (cst == null) {
     58             throw new NullPointerException("cst == null");
     59         }
     60 
     61         throwIfNotPrepared();
     62 
     63         Type type = ((CstType) cst).getClassType();
     64         IndexedItem result = typeIds.get(type);
     65 
     66         if (result == null) {
     67             throw new IllegalArgumentException("not found: " + cst);
     68         }
     69 
     70         return result;
     71     }
     72 
     73     /**
     74      * Writes the portion of the file header that refers to this instance.
     75      *
     76      * @param out {@code non-null;} where to write
     77      */
     78     public void writeHeaderPart(AnnotatedOutput out) {
     79         throwIfNotPrepared();
     80 
     81         int sz = typeIds.size();
     82         int offset = (sz == 0) ? 0 : getFileOffset();
     83 
     84         if (sz > 65536) {
     85             throw new UnsupportedOperationException("too many type ids");
     86         }
     87 
     88         if (out.annotates()) {
     89             out.annotate(4, "type_ids_size:   " + Hex.u4(sz));
     90             out.annotate(4, "type_ids_off:    " + Hex.u4(offset));
     91         }
     92 
     93         out.writeInt(sz);
     94         out.writeInt(offset);
     95     }
     96 
     97     /**
     98      * Interns an element into this instance.
     99      *
    100      * @param type {@code non-null;} the type to intern
    101      * @return {@code non-null;} the interned reference
    102      */
    103     public TypeIdItem intern(Type type) {
    104         if (type == null) {
    105             throw new NullPointerException("type == null");
    106         }
    107 
    108         throwIfPrepared();
    109 
    110         TypeIdItem result = typeIds.get(type);
    111 
    112         if (result == null) {
    113             result = new TypeIdItem(new CstType(type));
    114             typeIds.put(type, result);
    115         }
    116 
    117         return result;
    118     }
    119 
    120     /**
    121      * Interns an element into this instance.
    122      *
    123      * @param type {@code non-null;} the type to intern
    124      * @return {@code non-null;} the interned reference
    125      */
    126     public TypeIdItem intern(CstType type) {
    127         if (type == null) {
    128             throw new NullPointerException("type == null");
    129         }
    130 
    131         throwIfPrepared();
    132 
    133         Type typePerSe = type.getClassType();
    134         TypeIdItem result = typeIds.get(typePerSe);
    135 
    136         if (result == null) {
    137             result = new TypeIdItem(type);
    138             typeIds.put(typePerSe, result);
    139         }
    140 
    141         return result;
    142     }
    143 
    144     /**
    145      * Gets the index of the given type, which must have
    146      * been added to this instance.
    147      *
    148      * @param type {@code non-null;} the type to look up
    149      * @return {@code >= 0;} the reference's index
    150      */
    151     public int indexOf(Type type) {
    152         if (type == null) {
    153             throw new NullPointerException("type == null");
    154         }
    155 
    156         throwIfNotPrepared();
    157 
    158         TypeIdItem item = typeIds.get(type);
    159 
    160         if (item == null) {
    161             throw new IllegalArgumentException("not found: " + type);
    162         }
    163 
    164         return item.getIndex();
    165     }
    166 
    167     /**
    168      * Gets the index of the given type, which must have
    169      * been added to this instance.
    170      *
    171      * @param type {@code non-null;} the type to look up
    172      * @return {@code >= 0;} the reference's index
    173      */
    174     public int indexOf(CstType type) {
    175         if (type == null) {
    176             throw new NullPointerException("type == null");
    177         }
    178 
    179         return indexOf(type.getClassType());
    180     }
    181 
    182     /** {@inheritDoc} */
    183     @Override
    184     protected void orderItems() {
    185         int idx = 0;
    186 
    187         for (Object i : items()) {
    188             ((TypeIdItem) i).setIndex(idx);
    189             idx++;
    190         }
    191     }
    192 }
    193