blob: 50628fb87894efad3a190289d9c23a8e63a46dda [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package Mini;
import java.util.Vector;
/**
* For efficiency and convenience reasons we want our own hash table. It does
* not conform to java.util.Dictionary(yet).
*
* That environment contains all function definitions and identifiers.
* Hash keys are Strings (identifiers), which are mapped to a table index.
*
* The table consists of `SIZE' fields which have `SLOTS' subfields. Thus
* the maximum number of storable items is `SLOTS' * `SIZE'.
*
* @version $Id$
*/
public class Environment implements Cloneable {
private static final int SIZE = 127; // Prime number large enough for most cases
private static final int SLOTS = 3; // Number of slots of each field
private int size; // The table is an array of
private Vector<EnvEntry>[] table; // Vectors
private int elements=0;
public Environment(int size) {
this.size = size;
table = new Vector[size];
}
private Environment(Vector<EnvEntry>[] table) {
size = table.length;
this.table = table;
}
public Environment() {
this(SIZE);
}
private int hashCode(String key) {
return Math.abs(key.hashCode()) % size;
}
/**
* Inserts macro into table or overwrite old contents if it
* was already stored.
*/
public void put(EnvEntry obj) {
int hash;
Vector<EnvEntry> v;
String key = obj.getHashKey();
hash = hashCode(key);
v = table[hash];
elements++; // Count
if(v == null) {
table[hash] = v = new Vector<EnvEntry>(SLOTS);
} else {
try {
int index = lookup(v, key);
if(index >= 0) {
v.setElementAt(obj, index); // Overwrite
return;
}
} catch(ArrayIndexOutOfBoundsException e) {}
}
// Not found in Vector -> add it
v.addElement(obj);
}
/** Get entry from hash table.
*/
public EnvEntry get(String key) {
int hash;
Vector<EnvEntry> v;
EnvEntry entry = null;
hash = hashCode(key);
v = table[hash];
if(v == null) {
return null;
}
try {
int index = lookup(v, key);
if(index >= 0) {
entry = v.elementAt(index);
}
} catch(ArrayIndexOutOfBoundsException e) {}
return entry;
}
/**
* Delete an object if it does exist.
*/
public void delete(String key) {
int hash;
Vector<EnvEntry> v;
hash = hashCode(key);
v = table[hash];
if(v == null) {
return;
}
try {
int index = lookup(v, key);
if(index >= 0) {
elements--; // Count
v.removeElementAt(index);
}
} catch(ArrayIndexOutOfBoundsException e) {}
}
private static int lookup(Vector<EnvEntry> v, String key)
throws ArrayIndexOutOfBoundsException
{
int len = v.size();
for(int i=0; i < len; i++) {
EnvEntry entry = v.elementAt(i);
if(entry.getHashKey().equals(key)) {
return i;
}
}
return -1;
}
@Override
public Object clone() {
Vector<EnvEntry>[] copy = new Vector[size];
for(int i=0; i < size; i++) {
if(table[i] != null) {
copy[i] = (Vector)table[i].clone(); // Copies references
/*
int len = table[i].size();
copy[i] = new Vector(len);
try {
for(int j=0; j < len; j++)
copy[i].addElement(table[i].elementAt(j));
} catch(ArrayIndexOutOfBoundsException e) {}*/
}
}
return new Environment(copy);
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
for(int i=0; i < size; i++) {
if(table[i] != null) {
buf.append(table[i] + "\n");
}
}
return buf.toString();
}
public EnvEntry[] getEntries() {
EnvEntry[] entries = new EnvEntry[elements];
int k = 0;
Vector<EnvEntry> v;
for(int i=0; i < size; i++) {
if((v = table[i]) != null) {
int len = v.size();
try {
for(int j=0; j < len; j++) {
entries[k++] = v.elementAt(j);
}
} catch(ArrayIndexOutOfBoundsException e) {}
}
}
return entries;
}
}