/*******************************************************************************
* Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author ddaoust
* @noextend This class is not intended to be subclassed by clients.
*/
public class CharTable extends HashTable {
protected char[][] keyTable;
public CharTable(int initialSize) {
super(initialSize);
keyTable = new char[capacity()][];
}
@Override
protected void resize(int size) {
char[][] oldKeyTable = keyTable;
keyTable = new char[size][];
System.arraycopy(oldKeyTable, 0, keyTable, 0, Math.min(size, oldKeyTable.length));
super.resize(size);
}
@Override
public void clear() {
super.clear();
Arrays.fill(keyTable, null);
}
@Override
public Object clone() {
CharTable newTable = (CharTable) super.clone();
int size = capacity();
newTable.keyTable = new char[size][];
System.arraycopy(keyTable, 0, newTable.keyTable, 0, keyTable.length);
return newTable;
}
protected final int hash(char[] source, int start, int length) {
return hashTable == null ? 0 : hashToOffset(CharArrayUtils.hash(source, start, length));
}
@Override
protected final int hash(int pos) {
return hash(keyTable[pos], 0, keyTable[pos].length);
}
protected final int hash(char[] obj) {
return hash(obj, 0, obj.length);
}
protected final int addIndex(char[] buffer) {
return addIndex(buffer, 0, buffer.length);
}
public final int addIndex(char[] buffer, int start, int len) {
if (hashTable == null) {
int pos = lookup(buffer, start, len);
if (pos != -1)
return pos;
// Key is not here, add it.
if (currEntry + 1 >= capacity()) {
resize();
if (hashTable != null) {
// If we grew from list to hash, then recurse and add as a hashtable.
return addIndex(buffer, start, len);
}
}
currEntry++;
keyTable[currEntry] = CharArrayUtils.extract(buffer, start, len);
} else {
int hash = hash(buffer, start, len);
int pos = lookup(buffer, start, len, hash);
if (pos != -1)
return pos;
// Key is not here, add it.
if (currEntry + 1 >= capacity()) {
resize();
hash = hash(buffer, start, len);
}
currEntry++;
keyTable[currEntry] = CharArrayUtils.extract(buffer, start, len);
linkIntoHashTable(currEntry, hash);
}
return currEntry;
}
protected void removeEntry(int i) {
// Remove the entry from the keyTable, shifting everything over if necessary.
int hash = hash(keyTable[i]);
if (i < currEntry)
System.arraycopy(keyTable, i + 1, keyTable, i, currEntry - i);
keyTable[currEntry] = null;
// Make sure you remove the value before calling super where currEntry will change
removeEntry(i, hash);
}
public List<char[]> toList() {
List<char[]> list = new ArrayList<char[]>(size());
int size = size();
for (int i = 0; i < size; i++) {
list.add(keyAt(i));
}
return list;
}
public final char[] keyAt(int i) {
if (i < 0 || i > currEntry)
return null;
return keyTable[i];
}
public final boolean containsKey(char[] key, int start, int len) {
return lookup(key, start, len) != -1;
}
public final boolean containsKey(char[] key) {
return lookup(key) != -1;
}
public final char[] findKey(char[] buffer, int start, int len) {
int idx = lookup(buffer, start, len);
if (idx == -1)
return null;
return keyTable[idx];
}
public int lookup(char[] buffer) {
return lookup(buffer, 0, buffer.length);
}
protected final int lookup(char[] buffer, int start, int len) {
if (hashTable != null)
return lookup(buffer, start, len, hash(buffer, start, len));
for (int i = 0; i <= currEntry; i++) {
if (CharArrayUtils.equals(buffer, start, len, keyTable[i]))
return i;
}
return -1;
}
protected final int lookup(char[] buffer, int start, int len, int hash) {
int i = hashTable[hash];
if (i == 0)
return -1;
--i;
if (CharArrayUtils.equals(buffer, start, len, keyTable[i]))
return i;
// Follow the next chain.
for (i = nextTable[i] - 1; i >= 0 && i != nextTable[i] - 1; i = nextTable[i] - 1) {
if (CharArrayUtils.equals(buffer, start, len, keyTable[i]))
return i;
}
return -1;
}
/**
* @since 5.7
*/
public char[][] keys() {
char[][] keys = new char[size()][];
System.arraycopy(keyTable, 0, keys, 0, keys.length);
return keys;
}
/**
* @deprecated Use {@link #keys()} instead.
*/
@Deprecated
public Object[] keyArray() {
return keys();
}
}