12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.jimage; 27 28 import java.nio.charset.Charset; 29 import java.util.Arrays; 30 31 public final class UTF8String implements CharSequence { 32 33 // Same as StandardCharsets.UTF_8 without loading all of the standard charsets 34 static final Charset UTF_8 = Charset.forName("UTF-8"); 35 36 static final int NOT_FOUND = -1; 37 static final int HASH_MULTIPLIER = 0x01000193; 38 static final UTF8String EMPTY_STRING = new UTF8String(""); 39 static final UTF8String CLASS_STRING = new UTF8String(".class"); 40 41 final byte[] bytes; 42 final int offset; 43 final int count; 44 int hashcode; 45 46 public UTF8String(byte[] bytes, int offset, int count) { 47 if (offset < 0 || count < 0 || (offset + count) > bytes.length) { 48 throw new IndexOutOfBoundsException("offset/count out of range"); 49 } 50 this.bytes = bytes; 51 this.offset = offset; 52 this.count = count; 53 this.hashcode = -1; 54 } 55 56 public UTF8String(byte[] bytes, int offset) { 57 this(bytes, offset, bytes.length - offset); 58 } 59 143 if (byteAt(i) == ch) { 144 return i; 145 } 146 } 147 148 return NOT_FOUND; 149 } 150 151 void writeTo(ImageStream buffer) { 152 buffer.put(bytes, offset, count); 153 } 154 155 static int hashCode(int seed, byte[] bytes, int offset, int count) { 156 for (int i = offset, limit = offset + count; i < limit; i++) { 157 seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF); 158 } 159 160 return seed & 0x7FFFFFFF; 161 } 162 163 int hashCode(int base) { 164 return hashCode(base, bytes, offset, count); 165 } 166 167 @Override 168 public int hashCode() { 169 if (hashcode < 0) { 170 hashcode = hashCode(HASH_MULTIPLIER, bytes, offset, count); 171 } 172 173 return hashcode; 174 } 175 176 @Override 177 public boolean equals(Object obj) { 178 if (obj == null) { 179 return false; 180 } 181 182 if (getClass() != obj.getClass()) { 183 return false; 184 } 185 186 return equals(this, (UTF8String)obj); 187 } 188 189 private static boolean equals(UTF8String a, UTF8String b) { 190 if (a == b) { 191 return true; 192 } 193 194 int count = a.count; 195 196 if (count != b.count) { 197 return false; 198 } 199 200 byte[] aBytes = a.bytes; 201 byte[] bBytes = b.bytes; 202 int aOffset = a.offset; 203 int bOffset = b.offset; 204 205 for (int i = 0; i < count; i++) { 206 if (aBytes[aOffset + i] != bBytes[bOffset + i]) { 207 return false; 208 } 209 } 210 211 return true; 212 } 213 214 byte[] getBytes() { 215 if (offset != 0 || bytes.length != count) { 216 return Arrays.copyOfRange(bytes, offset, offset + count); 217 } 218 219 return bytes; 220 } 221 222 private static byte[] stringToBytes(String string) { 223 return string.getBytes(UTF_8); 224 } 225 226 @Override 227 public String toString() { 228 return new String(bytes, offset, count, UTF_8); 229 } 230 231 @Override 232 public char charAt(int index) { 233 int ch = byteAt(index); 234 235 return (ch & 0x80) != 0 ? (char)ch : '\0'; 236 } 237 238 @Override 239 public CharSequence subSequence(int start, int end) { 240 return (CharSequence)substring(start, end - start); 241 } 242 243 static UTF8String match(UTF8String a, UTF8String b) { 244 int aCount = a.count; 245 int bCount = b.count; 246 247 if (aCount < bCount) { 248 return null; 249 } 250 251 byte[] aBytes = a.bytes; 252 byte[] bBytes = b.bytes; 253 int aOffset = a.offset; 254 int bOffset = b.offset; 255 256 for (int i = 0; i < bCount; i++) { 257 if (aBytes[aOffset + i] != bBytes[bOffset + i]) { 258 return null; 259 } 260 } 261 262 return new UTF8String(aBytes, aOffset + bCount, aCount - bCount); 263 } 264 } | 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.jimage; 27 28 import java.nio.charset.Charset; 29 import java.util.Arrays; 30 31 public final class UTF8String implements CharSequence { 32 // Same as StandardCharsets.UTF_8 without loading all of the standard charsets 33 static final Charset UTF_8 = Charset.forName("UTF-8"); 34 35 static final int NOT_FOUND = -1; 36 static final int HASH_MULTIPLIER = 0x01000193; 37 static final UTF8String EMPTY_STRING = new UTF8String(""); 38 static final UTF8String SLASH_STRING = new UTF8String("/"); 39 static final UTF8String DOT_STRING = new UTF8String("."); 40 41 // TODO This strings are implementation specific and should be defined elsewhere. 42 static final UTF8String MODULES_STRING = new UTF8String("/modules"); 43 static final UTF8String PACKAGES_STRING = new UTF8String("/packages"); 44 45 final byte[] bytes; 46 final int offset; 47 final int count; 48 int hashcode; 49 50 public UTF8String(byte[] bytes, int offset, int count) { 51 if (offset < 0 || count < 0 || (offset + count) > bytes.length) { 52 throw new IndexOutOfBoundsException("offset/count out of range"); 53 } 54 this.bytes = bytes; 55 this.offset = offset; 56 this.count = count; 57 this.hashcode = -1; 58 } 59 60 public UTF8String(byte[] bytes, int offset) { 61 this(bytes, offset, bytes.length - offset); 62 } 63 147 if (byteAt(i) == ch) { 148 return i; 149 } 150 } 151 152 return NOT_FOUND; 153 } 154 155 void writeTo(ImageStream buffer) { 156 buffer.put(bytes, offset, count); 157 } 158 159 static int hashCode(int seed, byte[] bytes, int offset, int count) { 160 for (int i = offset, limit = offset + count; i < limit; i++) { 161 seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF); 162 } 163 164 return seed & 0x7FFFFFFF; 165 } 166 167 int hashCode(int seed) { 168 return hashCode(seed, bytes, offset, count); 169 } 170 171 @Override 172 public int hashCode() { 173 if (hashcode < 0) { 174 hashcode = hashCode(HASH_MULTIPLIER, bytes, offset, count); 175 } 176 177 return hashcode; 178 } 179 180 @Override 181 public boolean equals(Object obj) { 182 if (obj == null) { 183 return false; 184 } 185 186 if (getClass() != obj.getClass()) { 187 return false; 188 } 189 190 return equals(this, (UTF8String)obj); 191 } 192 193 public static boolean equals(UTF8String a, UTF8String b) { 194 if (a == b) { 195 return true; 196 } 197 198 int count = a.count; 199 200 if (count != b.count) { 201 return false; 202 } 203 204 byte[] aBytes = a.bytes; 205 byte[] bBytes = b.bytes; 206 int aOffset = a.offset; 207 int bOffset = b.offset; 208 209 for (int i = 0; i < count; i++) { 210 if (aBytes[aOffset + i] != bBytes[bOffset + i]) { 211 return false; 212 } 213 } 214 215 return true; 216 } 217 218 public byte[] getBytesCopy() { 219 return Arrays.copyOfRange(bytes, offset, offset + count); 220 } 221 222 byte[] getBytes() { 223 if (offset != 0 || bytes.length != count) { 224 return Arrays.copyOfRange(bytes, offset, offset + count); 225 } 226 227 return bytes; 228 } 229 230 private static byte[] stringToBytes(String string) { 231 return string.getBytes(UTF_8); 232 } 233 234 @Override 235 public String toString() { 236 return new String(bytes, offset, count, UTF_8); 237 } 238 239 @Override 240 public char charAt(int index) { 241 int ch = byteAt(index); 242 243 return (ch & 0x80) == 0 ? (char)ch : '\0'; 244 } 245 246 @Override 247 public CharSequence subSequence(int start, int end) { 248 return (CharSequence)substring(start, end - start); 249 } 250 } |