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