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