package org.apache.xerces.util;

public class SymbolHash {
  protected int fTableSize = 101;
  
  protected Entry[] fBuckets;
  
  protected int fNum = 0;
  
  public SymbolHash() {
    this.fBuckets = new Entry[this.fTableSize];
  }
  
  public SymbolHash(int size) {
    this.fTableSize = size;
    this.fBuckets = new Entry[this.fTableSize];
  }
  
  public void put(Object key, Object value) {
    int bucket = (key.hashCode() & Integer.MAX_VALUE) % this.fTableSize;
    Entry entry = search(key, bucket);
    if (entry != null) {
      entry.value = value;
    } else {
      entry = new Entry(key, value, this.fBuckets[bucket]);
      this.fBuckets[bucket] = entry;
      this.fNum++;
    } 
  }
  
  public Object get(Object key) {
    int bucket = (key.hashCode() & Integer.MAX_VALUE) % this.fTableSize;
    Entry entry = search(key, bucket);
    if (entry != null)
      return entry.value; 
    return null;
  }
  
  public int getLength() {
    return this.fNum;
  }
  
  public int getValues(Object[] elements, int from) {
    for (int i = 0, j = 0; i < this.fTableSize && j < this.fNum; i++) {
      for (Entry entry = this.fBuckets[i]; entry != null; entry = entry.next) {
        elements[from + j] = entry.value;
        j++;
      } 
    } 
    return this.fNum;
  }
  
  public SymbolHash makeClone() {
    SymbolHash newTable = new SymbolHash(this.fTableSize);
    newTable.fNum = this.fNum;
    for (int i = 0; i < this.fTableSize; i++) {
      if (this.fBuckets[i] != null)
        newTable.fBuckets[i] = this.fBuckets[i].makeClone(); 
    } 
    return newTable;
  }
  
  public void clear() {
    for (int i = 0; i < this.fTableSize; i++)
      this.fBuckets[i] = null; 
    this.fNum = 0;
  }
  
  protected Entry search(Object key, int bucket) {
    for (Entry entry = this.fBuckets[bucket]; entry != null; entry = entry.next) {
      if (key.equals(entry.key))
        return entry; 
    } 
    return null;
  }
  
  protected static final class Entry {
    public Object key;
    
    public Object value;
    
    public Entry next;
    
    public Entry() {
      this.key = null;
      this.value = null;
      this.next = null;
    }
    
    public Entry(Object key, Object value, Entry next) {
      this.key = key;
      this.value = value;
      this.next = next;
    }
    
    public Entry makeClone() {
      Entry entry = new Entry();
      entry.key = this.key;
      entry.value = this.value;
      if (this.next != null)
        entry.next = this.next.makeClone(); 
      return entry;
    }
  }
}
