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 */ StringIdsSection(DexFile file)45 public StringIdsSection(DexFile file) { 46 super("string_ids", file, 4); 47 48 strings = new TreeMap<CstUtf8, StringIdItem>(); 49 } 50 51 /** {@inheritDoc} */ 52 @Override items()53 public Collection<? extends Item> items() { 54 return strings.values(); 55 } 56 57 /** {@inheritDoc} */ 58 @Override get(Constant cst)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 */ writeHeaderPart(AnnotatedOutput out)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 */ intern(String string)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 */ intern(CstString string)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 */ intern(CstUtf8 string)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 */ intern(StringIdItem string)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 */ intern(CstNat nat)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 */ indexOf(CstUtf8 string)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 */ indexOf(CstString string)196 public int indexOf(CstString string) { 197 return indexOf(string.getString()); 198 } 199 200 /** {@inheritDoc} */ 201 @Override orderItems()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