1 /* 2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 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 com.sun.tools.javac.util; 27 28 import com.sun.tools.javac.jvm.ClassFile; 29 import com.sun.tools.javac.jvm.PoolConstant; 30 import com.sun.tools.javac.util.DefinedBy.Api; 31 32 /** An abstraction for internal compiler strings. They are stored in 33 * Utf8 format. Names are stored in a Name.Table, and are unique within 34 * that table. 35 * 36 * <p><b>This is NOT part of any supported API. 37 * If you write code that depends on this, you do so at your own risk. 38 * This code and its internal interfaces are subject to change or 39 * deletion without notice.</b> 40 */ 41 public abstract class Name implements javax.lang.model.element.Name, PoolConstant { 42 43 public final Table table; 44 Name(Table table)45 protected Name(Table table) { 46 this.table = table; 47 } 48 49 /** 50 * {@inheritDoc} 51 */ 52 @DefinedBy(Api.LANGUAGE_MODEL) contentEquals(CharSequence cs)53 public boolean contentEquals(CharSequence cs) { 54 return toString().equals(cs.toString()); 55 } 56 57 @Override poolTag()58 public int poolTag() { 59 return ClassFile.CONSTANT_Utf8; 60 } 61 62 /** 63 * {@inheritDoc} 64 */ length()65 public int length() { 66 return toString().length(); 67 } 68 69 /** 70 * {@inheritDoc} 71 */ charAt(int index)72 public char charAt(int index) { 73 return toString().charAt(index); 74 } 75 76 /** 77 * {@inheritDoc} 78 */ subSequence(int start, int end)79 public CharSequence subSequence(int start, int end) { 80 return toString().subSequence(start, end); 81 } 82 83 /** Return the concatenation of this name and name `n'. 84 */ append(Name n)85 public Name append(Name n) { 86 int len = getByteLength(); 87 byte[] bs = new byte[len + n.getByteLength()]; 88 getBytes(bs, 0); 89 n.getBytes(bs, len); 90 return table.fromUtf(bs, 0, bs.length); 91 } 92 93 /** Return the concatenation of this name, the given ASCII 94 * character, and name `n'. 95 */ append(char c, Name n)96 public Name append(char c, Name n) { 97 int len = getByteLength(); 98 byte[] bs = new byte[len + 1 + n.getByteLength()]; 99 getBytes(bs, 0); 100 bs[len] = (byte) c; 101 n.getBytes(bs, len+1); 102 return table.fromUtf(bs, 0, bs.length); 103 } 104 105 /** An arbitrary but consistent complete order among all Names. 106 */ compareTo(Name other)107 public int compareTo(Name other) { 108 return other.getIndex() - this.getIndex(); 109 } 110 111 /** Return true if this is the empty name. 112 */ isEmpty()113 public boolean isEmpty() { 114 return getByteLength() == 0; 115 } 116 117 /** Returns last occurrence of byte b in this name, -1 if not found. 118 */ lastIndexOf(byte b)119 public int lastIndexOf(byte b) { 120 byte[] bytes = getByteArray(); 121 int offset = getByteOffset(); 122 int i = getByteLength() - 1; 123 while (i >= 0 && bytes[offset + i] != b) i--; 124 return i; 125 } 126 127 /** Does this name start with prefix? 128 */ startsWith(Name prefix)129 public boolean startsWith(Name prefix) { 130 byte[] thisBytes = this.getByteArray(); 131 int thisOffset = this.getByteOffset(); 132 int thisLength = this.getByteLength(); 133 byte[] prefixBytes = prefix.getByteArray(); 134 int prefixOffset = prefix.getByteOffset(); 135 int prefixLength = prefix.getByteLength(); 136 137 if (thisLength < prefixLength) 138 return false; 139 140 int i = 0; 141 while (i < prefixLength && 142 thisBytes[thisOffset + i] == prefixBytes[prefixOffset + i]) 143 i++; 144 return i == prefixLength; 145 } 146 147 /** Returns the sub-name starting at position start, up to and 148 * excluding position end. 149 */ subName(int start, int end)150 public Name subName(int start, int end) { 151 if (end < start) end = start; 152 return table.fromUtf(getByteArray(), getByteOffset() + start, end - start); 153 } 154 155 /** Return the string representation of this name. 156 */ 157 @Override toString()158 public String toString() { 159 return Convert.utf2string(getByteArray(), getByteOffset(), getByteLength()); 160 } 161 162 /** Return the Utf8 representation of this name. 163 */ toUtf()164 public byte[] toUtf() { 165 byte[] bs = new byte[getByteLength()]; 166 getBytes(bs, 0); 167 return bs; 168 } 169 170 /* Get a "reasonably small" value that uniquely identifies this name 171 * within its name table. 172 */ getIndex()173 public abstract int getIndex(); 174 175 /** Get the length (in bytes) of this name. 176 */ getByteLength()177 public abstract int getByteLength(); 178 179 /** Returns i'th byte of this name. 180 */ getByteAt(int i)181 public abstract byte getByteAt(int i); 182 183 /** Copy all bytes of this name to buffer cs, starting at start. 184 */ getBytes(byte cs[], int start)185 public void getBytes(byte cs[], int start) { 186 System.arraycopy(getByteArray(), getByteOffset(), cs, start, getByteLength()); 187 } 188 189 /** Get the underlying byte array for this name. The contents of the 190 * array must not be modified. 191 */ getByteArray()192 public abstract byte[] getByteArray(); 193 194 /** Get the start offset of this name within its byte array. 195 */ getByteOffset()196 public abstract int getByteOffset(); 197 198 public interface NameMapper<X> { map(byte[] bytes, int offset, int len)199 X map(byte[] bytes, int offset, int len); 200 } 201 map(NameMapper<X> mapper)202 public <X> X map(NameMapper<X> mapper) { 203 return mapper.map(getByteArray(), getByteOffset(), getByteLength()); 204 } 205 206 /** An abstraction for the hash table used to create unique Name instances. 207 */ 208 public static abstract class Table { 209 /** Standard name table. 210 */ 211 public final Names names; 212 Table(Names names)213 Table(Names names) { 214 this.names = names; 215 } 216 217 /** Get the name from the characters in cs[start..start+len-1]. 218 */ fromChars(char[] cs, int start, int len)219 public abstract Name fromChars(char[] cs, int start, int len); 220 221 /** Get the name for the characters in string s. 222 */ fromString(String s)223 public Name fromString(String s) { 224 char[] cs = s.toCharArray(); 225 return fromChars(cs, 0, cs.length); 226 } 227 228 /** Get the name for the bytes in array cs. 229 * Assume that bytes are in utf8 format. 230 */ fromUtf(byte[] cs)231 public Name fromUtf(byte[] cs) { 232 return fromUtf(cs, 0, cs.length); 233 } 234 235 /** get the name for the bytes in cs[start..start+len-1]. 236 * Assume that bytes are in utf8 format. 237 */ fromUtf(byte[] cs, int start, int len)238 public abstract Name fromUtf(byte[] cs, int start, int len); 239 240 /** Release any resources used by this table. 241 */ dispose()242 public abstract void dispose(); 243 244 /** The hashcode of a name. 245 */ hashValue(byte bytes[], int offset, int length)246 protected static int hashValue(byte bytes[], int offset, int length) { 247 int h = 0; 248 int off = offset; 249 250 for (int i = 0; i < length; i++) { 251 h = (h << 5) - h + bytes[off++]; 252 } 253 return h; 254 } 255 256 /** Compare two subarrays 257 */ equals(byte[] bytes1, int offset1, byte[] bytes2, int offset2, int length)258 protected static boolean equals(byte[] bytes1, int offset1, 259 byte[] bytes2, int offset2, int length) { 260 int i = 0; 261 while (i < length && bytes1[offset1 + i] == bytes2[offset2 + i]) { 262 i++; 263 } 264 return i == length; 265 } 266 } 267 } 268