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.code.AccessFlags;
     20 import com.android.dexgen.rop.cst.CstFieldRef;
     21 import com.android.dexgen.rop.cst.CstUtf8;
     22 import com.android.dexgen.util.AnnotatedOutput;
     23 import com.android.dexgen.util.Hex;
     24 import com.android.dexgen.util.Leb128Utils;
     25 
     26 import java.io.PrintWriter;
     27 
     28 /**
     29  * Representation of a field of a class, of any sort.
     30  */
     31 public final class EncodedField extends EncodedMember
     32         implements Comparable<EncodedField> {
     33     /** {@code non-null;} constant for the field */
     34     private final CstFieldRef field;
     35 
     36     /**
     37      * Constructs an instance.
     38      *
     39      * @param field {@code non-null;} constant for the field
     40      * @param accessFlags access flags
     41      */
     42     public EncodedField(CstFieldRef field, int accessFlags) {
     43         super(accessFlags);
     44 
     45         if (field == null) {
     46             throw new NullPointerException("field == null");
     47         }
     48 
     49         /*
     50          * TODO: Maybe check accessFlags, at least for
     51          * easily-checked stuff?
     52          */
     53 
     54         this.field = field;
     55     }
     56 
     57     /** {@inheritDoc} */
     58     public int hashCode() {
     59         return field.hashCode();
     60     }
     61 
     62     /** {@inheritDoc} */
     63     public boolean equals(Object other) {
     64         if (! (other instanceof EncodedField)) {
     65             return false;
     66         }
     67 
     68         return compareTo((EncodedField) other) == 0;
     69     }
     70 
     71     /**
     72      * {@inheritDoc}
     73      *
     74      * <p><b>Note:</b> This compares the method constants only,
     75      * ignoring any associated code, because it should never be the
     76      * case that two different items with the same method constant
     77      * ever appear in the same list (or same file, even).</p>
     78      */
     79     public int compareTo(EncodedField other) {
     80         return field.compareTo(other.field);
     81     }
     82 
     83     /** {@inheritDoc} */
     84     @Override
     85     public String toString() {
     86         StringBuffer sb = new StringBuffer(100);
     87 
     88         sb.append(getClass().getName());
     89         sb.append('{');
     90         sb.append(Hex.u2(getAccessFlags()));
     91         sb.append(' ');
     92         sb.append(field);
     93         sb.append('}');
     94         return sb.toString();
     95     }
     96 
     97     /** {@inheritDoc} */
     98     @Override
     99     public void addContents(DexFile file) {
    100         FieldIdsSection fieldIds = file.getFieldIds();
    101         fieldIds.intern(field);
    102     }
    103 
    104     /** {@inheritDoc} */
    105     @Override
    106     public CstUtf8 getName() {
    107         return field.getNat().getName();
    108     }
    109 
    110     /** {@inheritDoc} */
    111     public String toHuman() {
    112         return field.toHuman();
    113     }
    114 
    115     /** {@inheritDoc} */
    116     @Override
    117     public void debugPrint(PrintWriter out, boolean verbose) {
    118         // TODO: Maybe put something better here?
    119         out.println(toString());
    120     }
    121 
    122     /**
    123      * Gets the constant for the field.
    124      *
    125      * @return {@code non-null;} the constant
    126      */
    127     public CstFieldRef getRef() {
    128         return field;
    129     }
    130 
    131     /** {@inheritDoc} */
    132     @Override
    133     public int encode(DexFile file, AnnotatedOutput out,
    134             int lastIndex, int dumpSeq) {
    135         int fieldIdx = file.getFieldIds().indexOf(field);
    136         int diff = fieldIdx - lastIndex;
    137         int accessFlags = getAccessFlags();
    138 
    139         if (out.annotates()) {
    140             out.annotate(0, String.format("  [%x] %s", dumpSeq,
    141                             field.toHuman()));
    142             out.annotate(Leb128Utils.unsignedLeb128Size(diff),
    143                     "    field_idx:    " + Hex.u4(fieldIdx));
    144             out.annotate(Leb128Utils.unsignedLeb128Size(accessFlags),
    145                     "    access_flags: " +
    146                     AccessFlags.fieldString(accessFlags));
    147         }
    148 
    149         out.writeUnsignedLeb128(diff);
    150         out.writeUnsignedLeb128(accessFlags);
    151 
    152         return fieldIdx;
    153     }
    154 }
    155