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.CstNat;
     21 import com.android.dexgen.rop.cst.CstString;
     22 import com.android.dexgen.rop.cst.CstUtf8;
     23 import com.android.dexgen.util.AnnotatedOutput;
     24 import com.android.dexgen.util.Hex;
     25 
     26 import java.util.Collection;
     27 import java.util.TreeMap;
     28 
     29 /**
     30  * Strings list section of a {@code .dex} file.
     31  */
     32 public final class StringIdsSection
     33         extends UniformItemSection {
     34     /**
     35      * {@code non-null;} map from string constants to {@link
     36      * StringIdItem} instances
     37      */
     38     private final TreeMap<CstUtf8, StringIdItem> strings;
     39 
     40     /**
     41      * Constructs an instance. The file offset is initially unknown.
     42      *
     43      * @param file {@code non-null;} file that this instance is part of
     44      */
     45     public StringIdsSection(DexFile file) {
     46         super("string_ids", file, 4);
     47 
     48         strings = new TreeMap<CstUtf8, StringIdItem>();
     49     }
     50 
     51     /** {@inheritDoc} */
     52     @Override
     53     public Collection<? extends Item> items() {
     54         return strings.values();
     55     }
     56 
     57     /** {@inheritDoc} */
     58     @Override
     59     public IndexedItem get(Constant cst) {
     60         if (cst == null) {
     61             throw new NullPointerException("cst == null");
     62         }
     63 
     64         throwIfNotPrepared();
     65 
     66         if (cst instanceof CstString) {
     67             cst = ((CstString) cst).getString();
     68         }
     69 
     70         IndexedItem result = strings.get((CstUtf8) cst);
     71 
     72         if (result == null) {
     73             throw new IllegalArgumentException("not found");
     74         }
     75 
     76         return result;
     77     }
     78 
     79     /**
     80      * Writes the portion of the file header that refers to this instance.
     81      *
     82      * @param out {@code non-null;} where to write
     83      */
     84     public void writeHeaderPart(AnnotatedOutput out) {
     85         throwIfNotPrepared();
     86 
     87         int sz = strings.size();
     88         int offset = (sz == 0) ? 0 : getFileOffset();
     89 
     90         if (out.annotates()) {
     91             out.annotate(4, "string_ids_size: " + Hex.u4(sz));
     92             out.annotate(4, "string_ids_off:  " + Hex.u4(offset));
     93         }
     94 
     95         out.writeInt(sz);
     96         out.writeInt(offset);
     97     }
     98 
     99     /**
    100      * Interns an element into this instance.
    101      *
    102      * @param string {@code non-null;} the string to intern, as a regular Java
    103      * {@code String}
    104      * @return {@code non-null;} the interned string
    105      */
    106     public StringIdItem intern(String string) {
    107         CstUtf8 utf8 = new CstUtf8(string);
    108         return intern(new StringIdItem(utf8));
    109     }
    110 
    111     /**
    112      * Interns an element into this instance.
    113      *
    114      * @param string {@code non-null;} the string to intern, as a {@link CstString}
    115      * @return {@code non-null;} the interned string
    116      */
    117     public StringIdItem intern(CstString string) {
    118         CstUtf8 utf8 = string.getString();
    119         return intern(new StringIdItem(utf8));
    120     }
    121 
    122     /**
    123      * Interns an element into this instance.
    124      *
    125      * @param string {@code non-null;} the string to intern, as a constant
    126      * @return {@code non-null;} the interned string
    127      */
    128     public StringIdItem intern(CstUtf8 string) {
    129         return intern(new StringIdItem(string));
    130     }
    131 
    132     /**
    133      * Interns an element into this instance.
    134      *
    135      * @param string {@code non-null;} the string to intern
    136      * @return {@code non-null;} the interned string
    137      */
    138     public StringIdItem intern(StringIdItem string) {
    139         if (string == null) {
    140             throw new NullPointerException("string == null");
    141         }
    142 
    143         throwIfPrepared();
    144 
    145         CstUtf8 value = string.getValue();
    146         StringIdItem already = strings.get(value);
    147 
    148         if (already != null) {
    149             return already;
    150         }
    151 
    152         strings.put(value, string);
    153         return string;
    154     }
    155 
    156     /**
    157      * Interns the components of a name-and-type into this instance.
    158      *
    159      * @param nat {@code non-null;} the name-and-type
    160      */
    161     public void intern(CstNat nat) {
    162         intern(nat.getName());
    163         intern(nat.getDescriptor());
    164     }
    165 
    166     /**
    167      * Gets the index of the given string, which must have been added
    168      * to this instance.
    169      *
    170      * @param string {@code non-null;} the string to look up
    171      * @return {@code >= 0;} the string's index
    172      */
    173     public int indexOf(CstUtf8 string) {
    174         if (string == null) {
    175             throw new NullPointerException("string == null");
    176         }
    177 
    178         throwIfNotPrepared();
    179 
    180         StringIdItem s = strings.get(string);
    181 
    182         if (s == null) {
    183             throw new IllegalArgumentException("not found");
    184         }
    185 
    186         return s.getIndex();
    187     }
    188 
    189     /**
    190      * Gets the index of the given string, which must have been added
    191      * to this instance.
    192      *
    193      * @param string {@code non-null;} the string to look up
    194      * @return {@code >= 0;} the string's index
    195      */
    196     public int indexOf(CstString string) {
    197         return indexOf(string.getString());
    198     }
    199 
    200     /** {@inheritDoc} */
    201     @Override
    202     protected void orderItems() {
    203         int idx = 0;
    204 
    205         for (StringIdItem s : strings.values()) {
    206             s.setIndex(idx);
    207             idx++;
    208         }
    209     }
    210 }
    211