Home | History | Annotate | Download | only in file
      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 
     17 package com.android.dx.dex.file;
     18 
     19 import com.android.dx.dex.SizeOf;
     20 import com.android.dx.rop.cst.CstString;
     21 import com.android.dx.rop.type.Prototype;
     22 import com.android.dx.rop.type.StdTypeList;
     23 import com.android.dx.rop.type.Type;
     24 import com.android.dx.util.AnnotatedOutput;
     25 import com.android.dx.util.Hex;
     26 
     27 /**
     28  * Representation of a method prototype reference inside a Dalvik file.
     29  */
     30 public final class ProtoIdItem extends IndexedItem {
     31     /** {@code non-null;} the wrapped prototype */
     32     private final Prototype prototype;
     33 
     34     /** {@code non-null;} the short-form of the prototype */
     35     private final CstString shortForm;
     36 
     37     /**
     38      * {@code null-ok;} the list of parameter types or {@code null} if this
     39      * prototype has no parameters
     40      */
     41     private TypeListItem parameterTypes;
     42 
     43     /**
     44      * Constructs an instance.
     45      *
     46      * @param prototype {@code non-null;} the constant for the prototype
     47      */
     48     public ProtoIdItem(Prototype prototype) {
     49         if (prototype == null) {
     50             throw new NullPointerException("prototype == null");
     51         }
     52 
     53         this.prototype = prototype;
     54         this.shortForm = makeShortForm(prototype);
     55 
     56         StdTypeList parameters = prototype.getParameterTypes();
     57         this.parameterTypes = (parameters.size() == 0) ? null
     58             : new TypeListItem(parameters);
     59     }
     60 
     61     /**
     62      * Creates the short-form of the given prototype.
     63      *
     64      * @param prototype {@code non-null;} the prototype
     65      * @return {@code non-null;} the short form
     66      */
     67     private static CstString makeShortForm(Prototype prototype) {
     68         StdTypeList parameters = prototype.getParameterTypes();
     69         int size = parameters.size();
     70         StringBuilder sb = new StringBuilder(size + 1);
     71 
     72         sb.append(shortFormCharFor(prototype.getReturnType()));
     73 
     74         for (int i = 0; i < size; i++) {
     75             sb.append(shortFormCharFor(parameters.getType(i)));
     76         }
     77 
     78         return new CstString(sb.toString());
     79     }
     80 
     81     /**
     82      * Gets the short-form character for the given type.
     83      *
     84      * @param type {@code non-null;} the type
     85      * @return the corresponding short-form character
     86      */
     87     private static char shortFormCharFor(Type type) {
     88         char descriptorChar = type.getDescriptor().charAt(0);
     89 
     90         if (descriptorChar == '[') {
     91             return 'L';
     92         }
     93 
     94         return descriptorChar;
     95     }
     96 
     97     /** {@inheritDoc} */
     98     @Override
     99     public ItemType itemType() {
    100         return ItemType.TYPE_PROTO_ID_ITEM;
    101     }
    102 
    103     /** {@inheritDoc} */
    104     @Override
    105     public int writeSize() {
    106         return SizeOf.PROTO_ID_ITEM;
    107     }
    108 
    109     /** {@inheritDoc} */
    110     @Override
    111     public void addContents(DexFile file) {
    112         StringIdsSection stringIds = file.getStringIds();
    113         TypeIdsSection typeIds = file.getTypeIds();
    114         MixedItemSection typeLists = file.getTypeLists();
    115 
    116         typeIds.intern(prototype.getReturnType());
    117         stringIds.intern(shortForm);
    118 
    119         if (parameterTypes != null) {
    120             parameterTypes = typeLists.intern(parameterTypes);
    121         }
    122     }
    123 
    124     /** {@inheritDoc} */
    125     @Override
    126     public void writeTo(DexFile file, AnnotatedOutput out) {
    127         int shortyIdx = file.getStringIds().indexOf(shortForm);
    128         int returnIdx = file.getTypeIds().indexOf(prototype.getReturnType());
    129         int paramsOff = OffsettedItem.getAbsoluteOffsetOr0(parameterTypes);
    130 
    131         if (out.annotates()) {
    132             StringBuilder sb = new StringBuilder();
    133             sb.append(prototype.getReturnType().toHuman());
    134             sb.append(" proto(");
    135 
    136             StdTypeList params = prototype.getParameterTypes();
    137             int size = params.size();
    138 
    139             for (int i = 0; i < size; i++) {
    140                 if (i != 0) {
    141                     sb.append(", ");
    142                 }
    143                 sb.append(params.getType(i).toHuman());
    144             }
    145 
    146             sb.append(")");
    147             out.annotate(0, indexString() + ' ' + sb.toString());
    148             out.annotate(4, "  shorty_idx:      " + Hex.u4(shortyIdx) +
    149                     " // " + shortForm.toQuoted());
    150             out.annotate(4, "  return_type_idx: " + Hex.u4(returnIdx) +
    151                     " // " + prototype.getReturnType().toHuman());
    152             out.annotate(4, "  parameters_off:  " + Hex.u4(paramsOff));
    153         }
    154 
    155         out.writeInt(shortyIdx);
    156         out.writeInt(returnIdx);
    157         out.writeInt(paramsOff);
    158     }
    159 }
    160