/*
* TclIndex.java
*
* This file implements objects of type "index". This object type
* is used to lookup a keyword in a table of valid values and cache
* the index of the matching entry.
*
* Copyright (c) 1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*
* RCS: @(#) $Id: TclIndex.java,v 1.6 2005/10/11 20:03:23 mdejong Exp $
*/
package tcl.lang;
public class TclIndex implements InternalRep {
/**
* The variable slots for this object.
*/
private int index;
/**
* Table of valid options.
*/
private String[] table;
/**
* Construct a TclIndex representation with the given index & table.
*/
private TclIndex(int i, String[] tab) {
index = i;
table = tab;
}
/**
* Returns a dupilcate of the current object.
* @param obj the TclObject that contains this internalRep.
*/
public InternalRep duplicate() {
return new TclIndex(index, table);
}
/**
* Implement this no-op for the InternalRep interface.
*/
public void dispose() {}
/**
* Called to query the string representation of the Tcl object. This
* method is called only by TclObject.toString() when
* TclObject.stringRep is null.
*
* @return the string representation of the Tcl object.
*/
public String toString() {
return table[index];
}
/**
* Tcl_GetIndexFromObj -> get
*
* Gets the index into the table of the object. Generate an error
* it it doesn't occur. This also converts the object to an index
* which should catch the lookup for speed improvement.
*
* @param interp the interperter or null
* @param tobj the object to operate on.
* @paran table the list of commands
* @paran msg used as part of any error messages
* @paran flags may be TCL.EXACT.
*/
public static int get(Interp interp, TclObject tobj, String[] table,
String msg, int flags) throws TclException {
InternalRep rep = tobj.getInternalRep();
if (rep instanceof TclIndex) {
if (((TclIndex) rep).table == table) {
return ((TclIndex) rep).index;
}
}
String str = tobj.toString();
int strLen = str.length();
int tableLen = table.length;
int index = -1;
int numAbbrev = 0;
checking: {
if (strLen > 0) {
for (int i = 0; i < tableLen; i++) {
String option = table[i];
if (((flags & TCL.EXACT) == TCL.EXACT) &&
(option.length() != strLen)) {
continue;
}
if (option.equals(str)) {
// Found an exact match already. Return it.
index = i;
break checking;
}
if (option.startsWith(str)) {
numAbbrev++;
index = i;
}
}
}
if (numAbbrev != 1) {
StringBuffer sbuf = new StringBuffer();
if (numAbbrev > 1) {
sbuf.append("ambiguous ");
} else {
sbuf.append("bad ");
}
sbuf.append(msg);
sbuf.append(" \"");
sbuf.append(str);
sbuf.append("\"");
sbuf.append(": must be ");
sbuf.append(table[0]);
for (int i = 1; i < tableLen; i++) {
if (i == (tableLen - 1)) {
sbuf.append((i>1) ? ", or " : " or ");
} else {
sbuf.append(", ");
}
sbuf.append(table[i]);
}
throw new TclException(interp, sbuf.toString());
}
}
// Create a new index object.
tobj.setInternalRep(new TclIndex(index, table));
return index;
}
/**
* Invoked only when testing the TclIndex implementation in TestObjCmd.java
*/
void testUpdateIndex(int index) {
this.index = index;
}
}