FileDocCategorySizeDatePackage
KVMHashtable.javaAPI DocJ2ME CLDC 1.14746Wed Feb 05 15:56:02 GMT 2003runtime

KVMHashtable.java

/*
 *    KVMHashtable.java    1.4    03/01/14
 *
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package runtime;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

abstract 
public class KVMHashtable { 
    Class type;
    private int size;
    boolean closed;  // Cannot add any more entries
    private Object firstEntry[];
    private Hashtable nextEntry = new Hashtable();
    private Hashtable seen = new Hashtable();
    private Hashtable keys = new Hashtable();

    public Enumeration enumerate() { 
        return seen.keys();
    }

    static public long 
    stringHash(String string) { 
        int raw_hash = 0;
        for (int i = 0; i < string.length(); i++) { 
            raw_hash = raw_hash * 37 + string.charAt(i);
        }
        long result = (((long)raw_hash) << 32) >>> 32;
        return result;
    }

    KVMHashtable(int size, Class type) { 
        this.size = size;
        firstEntry = new Object[size];
        this.type = type;
        this.closed = false;
    }

    abstract long hash(Object x);

    public void chainPrefix(CCodeWriter c) {};
    abstract Object tableChain(CCodeWriter c, int bucket, Object[] chain);    
    public void chainSuffix(CCodeWriter c) {};

    abstract void tableEntry(CCodeWriter c, int bucket, Object token);

    public void addNewEntryCallback(int bucket, Object neww) {}

    public void addEntry(Object x) { 
        if (closed) {
            throw new Error("Hashtable is closed");
        } 
        // Don't do anything if we've already seen this guy.
        if (seen.get(x) != null) { 
            return;
        }
        checkType(x);
        seen.put(x, x);
        int bucket = (int)(hash(x) % size);
        if (bucket < 0) { 
            System.out.println("Bad bucket?? " + this);
        }
        // Add this guy to the beginning of his bucket.
        Object oldNext = firstEntry[bucket];
        firstEntry[bucket] = x;
        if (oldNext != null) { 
            nextEntry.put(x, oldNext);
        }
        addNewEntryCallback(bucket, x);
    }

    protected Object getFirst(int bucket) { 
        return firstEntry[bucket];
    }

    protected Object getNext(Object x) { 
        checkType(x);
        return nextEntry.get(x);
    }

    int getSize() { 
        return size;
    }

    protected void setKey(Object x, int key) { 
        checkType(x);
        Integer Key = new Integer(key);
        Object oldKey = keys.put(x, Key);
        Object oldVal = keys.put(Key, x);
        if (oldKey != null) { 
            System.out.println("Changing key(" + x + ") from " + oldKey + " to "
                   + Key);
        }
        if (oldVal != null) { 
            System.out.println("Both " + x + " and " + oldVal 
                   + " have the same key value " + Key);
        }
    }

    protected int getKey(Object x) { 
        Integer Key = (Integer)keys.get(x);
        if (Key == null) { 
            addEntry(x);
            Key = (Integer)keys.get(x);
        } 
        return Key.intValue();
    }

    protected Object getObject(int key) { 
        return keys.get(new Integer(key));
    }

    void writeTable(CCodeWriter out, String tableName) { 
        closed = true;
        chainPrefix(out);
        Vector list = new Vector();
        Object tokens[] = new Object[size];
        for (int i = 0; i < size; i++) { 
            list.setSize(0);
            for (Object item = firstEntry[i]; item != null; 
                item = nextEntry.get(item)) { 
                list.addElement(item);
            }
            Object[] listArray = new Object[list.size()];
            list.copyInto(listArray);
            tokens[i] = tableChain(out, i, listArray);
        }
        chainSuffix(out);

        out.println("static HASHTABLE_X(" + size + ") " + tableName + "Data = {");
        out.println("\tHASHTABLE_HEADER(" + size + ", " + seen.size() + "),");
        out.println("\t{");
        for (int i = 0; i < size; i++) { 
            if (tokens[i] == null) { 
                out.print("\t\tNULL,\n");
            } else { 
                out.print("\t\t((void *)");
                tableEntry(out, i, tokens[i]);
                out.print("),\n");
            }
        }
        out.println("\t}");
        out.println("};\n");    
        out.println("#if !RELOCATABLE_ROM");
        out.println("HASHTABLE " + tableName + " = (HASHTABLE)&" + tableName + "Data;\n");
        out.println("#endif");
    }
    
    private void checkType(Object x) {
        if (!type.isAssignableFrom(x.getClass())) {
            throw new Error(x.getClass() + " is not assignable to " + type);
        }
    }
}