FileDocCategorySizeDatePackage
Str2ID.javaAPI DocJ2ME CLDC 1.14893Wed Feb 05 15:56:02 GMT 2003jcc

Str2ID.java

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

package jcc;

import components.UnicodeConstant;
import components.StringConstant;
import util.Localizer;

/*
 * This class duplicates the String to ID hashing that Java
 * does internally.  An initial set of hash tables is produced
 * that the Java runtime will use.
 * (perhaps this really belongs in package vm?)
 */

public
class Str2ID
{
    // The contents of each hash table chain
    public int hashTableSize;
    public int            used = 0;
    public int           baseId = 1;
    public Str2ID       next = null;
    public UnicodeConstant strings[];
    public StringConstant  parameters[] = null;
    public int            hashbits[];
    
    boolean locked = false;    // check that nothing new is added.

    public static final int DEFAULT_hashTableSize = 2003;

    public Str2ID() { 
        this(DEFAULT_hashTableSize, true);
    }

    public Str2ID(int size) { 
        this(size, false);
    }

    private Str2ID(int size, boolean knownPrime) { 
        if (!knownPrime) { 
        size |= 1;
        while (!isPrime(size))
            size += 2;
    }
    hashTableSize = size;
    strings = new UnicodeConstant[size];
    hashbits = new int[size];
    overflowPoint = (int)(hashTableSize * 0.8);
    }

    // Use values in java/util/util.c

    int overflowPoint;
    public static Str2ID sigHash = new Str2ID();

    // Treat val as an unsigned quantity and do the MOD operation
    int unsignedMod(int val) {
    if (val >= 0) {
        return val % hashTableSize;
    } else {
        return (int)(((long)val&0xffffffffL) % (long)hashTableSize);
    }
    }
    

    static int hashString(String str) {
    int result = 0;
    for (int i = 0; i < str.length(); i++) {
        result = result * 37 + (int) str.charAt(i);
    }

    return result;
    }
    

    public int getID( UnicodeConstant str, StringConstant parameter ) {
    Str2ID head = this;
    int index;
    int hash = hashString(str.string);
    int phash = hash & 0x7fffffff;
    int secondaryHash = (hash & 7) + 1;

    Str2ID chain = head;
    for ( ; ; ) {
        index = chain.unsignedMod(hash);
        while (chain.strings[index] != null) {
        if ((chain.hashbits[index] == phash) &&
            chain.strings[index].string.equals(str.string)) {
            // We found the string, calculate the ID
            return chain.baseId + index;
        }
        index -= secondaryHash;
        if (index < 0) {
            index += chain.hashTableSize;
        }
        }

        // Didn't find the string in this chain. . . .
        if (chain.next == null) { 
            break;
        } else { 
            chain = chain.next;
        }
    }

    if (locked) { 
        throw new NullPointerException(
        Localizer.getString("str2id.attempting_to_add_to_table_when_locked", str));

    }
    if (chain.used >= chain.overflowPoint) {
        chain.next = new Str2ID();
        chain.next.baseId = chain.baseId + chain.hashTableSize;
        chain = chain.next;
        index = chain.unsignedMod(hash);
    }

    chain.strings[index] = str;
    chain.hashbits[index] = phash;
    if (parameter != null ){
        if ( chain.parameters == null ){
        chain.parameters = new StringConstant[chain.hashTableSize];
        }
        chain.parameters[index] = parameter;
    }
    chain.used++;
    return chain.baseId + index;
    }

    public int getID(String str) {
    return getID( new UnicodeConstant( str ), (StringConstant)null );
    }

    public int getID(UnicodeConstant name, UnicodeConstant sig) {
    return (getID( name, (StringConstant)null) << 16) + getID( sig, (StringConstant)null);
    }

    public int getID(String name, String sig) {
    return (getID(name) << 16) + getID(sig);
    }

    public void setLocked(boolean lock) { 
        this.locked = lock;
    }

    public Str2ID rehash() {
        Str2ID newchain, chain;
    int count = 0;
    for (chain = this; chain != null; chain = chain.next) {
        count += chain.used;
    }
    newchain = new Str2ID((int)Math.ceil(1.25 * count));

    for (chain = this; chain != null; chain = chain.next) {
        UnicodeConstant strings[] = chain.strings;
        StringConstant  parameters[] = chain.parameters;
        for (int i = chain.hashTableSize; --i >= 0; ) { 
            UnicodeConstant string = strings[i];
        if (string != null) 
            newchain.getID(string, parameters == null ? null : parameters[i]);
        }
    }
    return newchain;
    }

    static boolean isPrime(int n){
        if ((n % 2) == 0)
        return false;
    int sqrt = (int) Math.sqrt(n);
    for (int i = 3; i <= sqrt; i += 2) { 
        if ((n % i) == 0)
            return false;
    }
    return true;
    }
}