|
|
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */
// $Id$
package scalac.util;
import java.util.HashMap;
/** Instances of this class represent term names. */
public final class TermName extends Name {
//########################################################################
// Private Variables
/** Hashtable from string representation to term names. */
private static HashMap/*<String,TermName>*/ strings = new HashMap();
/** Hashtable from ASCII representation to term names. */
private static TermName[] asciis = new TermName[0x00008000];
//########################################################################
// Private Fields
/** The string representation */
private final String string;
/** The ASCII representation (null if not yet computed) */
private byte[] ascii;
/** The next name stored in the same bucket of the ASCII table */
private TermName next;
//########################################################################
// Private Constructors
/** Initializes this instance. */
private TermName(String string) {
super(2 * strings.size(), null);
this.string = string;
strings.put(string, this);
}
//########################################################################
// Public Factories
/** Returns the term name with given ASCII representation. */
public static TermName fromAscii(byte[] bytes, int start, int count) {
int index = hashValue(bytes, start, count) & (asciis.length - 1);
for (TermName name = asciis[index]; name != null; name = name.next)
if (name.equals(bytes, start, count)) return name;
TermName name = fromString(
SourceRepresentation.ascii2string(bytes, start, count));
byte[] ascii = new byte[count];
for (int i = 0; i < ascii.length; i++) ascii[i] = bytes[start + i];
name.setAscii(ascii, index);
return name;
}
/** Returns the term name with given string representation. */
public static TermName fromString(String string) {
Object value = strings.get(string);
return value != null ? (TermName)value : new TermName(string);
}
//########################################################################
// Public Methods
/** Returns the string representation of this name. */
public String toString() {
return string;
}
/**
* Returns the ASCII representation of this name. The returned
* array is not a copy. Therefore, it is forbidden to modify it.
*/
public byte[] toAsciiUnsafe() {
if (ascii == null) {
byte[] ascii = SourceRepresentation.string2ascii(string);
int index = hashValue(ascii, 0, ascii.length) & (asciis.length-1);
setAscii(ascii, index);
}
return ascii;
}
//########################################################################
// Private Methods & Functions
/** Sets the ASCII representation to given one. */
private void setAscii(byte[] ascii, int index) {
assert this.ascii == null: this;
this.ascii = ascii;
this.next = asciis[index];
asciis[index] = this;
}
/** Is this name's ASCII representations equal to given one? */
private boolean equals(byte[] bytes, int start, int count) {
if (ascii.length != count) return false;
for (int i = 0; i < count; i++)
if (ascii[i] != bytes[start + i]) return false;
return true;
}
/** Returns the hash code of the ASCII representation. */
private static int hashValue(byte[] bytes, int start, int count) {
if (count <= 0) return 0;
return count * (41 * 41 * 41)
+ bytes[start] * (41 * 41)
+ bytes[start + count - 1] * 41
+ bytes[start + (count >> 1)];
}
//########################################################################
}
|