mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-02 22:55:26 +02:00
New character array utilities that should make things much faster, one day...
This commit is contained in:
parent
764632f0c3
commit
c839041374
4 changed files with 366 additions and 0 deletions
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Created on May 28, 2004
|
||||
*
|
||||
* TODO To change the template for this generated file go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
package org.eclipse.cdt.core.parser.tests;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.cdt.core.parser.CharArrayMap;
|
||||
import org.eclipse.cdt.core.parser.CharArrayPool;
|
||||
import org.eclipse.cdt.core.parser.CharArrayUtils;
|
||||
|
||||
/**
|
||||
* @author dschaefe
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public class CharArrayUtilsTest extends TestCase {
|
||||
|
||||
public void testPoolAdd() {
|
||||
CharArrayPool dict = new CharArrayPool(1);
|
||||
|
||||
char[] str1 = new char[] {'h', 'e', 'l', 'l', 'o'};
|
||||
char[] str2 = dict.add(str1);
|
||||
assertTrue(CharArrayUtils.equals(str1, str2));
|
||||
assertNotSame(str1, str2);
|
||||
char[] str3 = dict.add(str1);
|
||||
assertSame(str2, str3);
|
||||
|
||||
char[] str4 = new char[] {'w', 'o', 'r', 'l', 'd'};
|
||||
char[] str5 = dict.add(str4, 0, str4.length);
|
||||
assertTrue(CharArrayUtils.equals(str4, str5));
|
||||
assertNotSame(str4, str5);
|
||||
char[] str6 = dict.add(str4);
|
||||
assertSame(str5, str6);
|
||||
|
||||
char[] str7 = dict.add(str1, 0, str1.length);
|
||||
assertTrue(CharArrayUtils.equals(str1, str7));
|
||||
assertNotSame(str1, str7);
|
||||
char[] str8 = dict.add(str1);
|
||||
assertSame(str7, str8);
|
||||
}
|
||||
|
||||
public void testPoolConflict() {
|
||||
CharArrayPool dict = new CharArrayPool(2);
|
||||
|
||||
char[] str1 = new char[] {'h', 'e', 'l', 'l', 'o'};
|
||||
char[] str2 = dict.add(str1);
|
||||
|
||||
// The hash algorithm should give this the same hash code
|
||||
char[] str3 = new char[] {'h', 'o', 'l', 'l', 'e'};
|
||||
char[] str4 = dict.add(str3);
|
||||
assertNotSame(str2, str4);
|
||||
|
||||
char[] str5 = dict.add(str1);
|
||||
assertTrue(CharArrayUtils.equals(str1, str5));
|
||||
|
||||
char[] str6 = new char[] {'w', 'o', 'r', 'l', 'd'};
|
||||
char[] str7 = dict.add(str6);
|
||||
assertTrue(CharArrayUtils.equals(str6, str7));
|
||||
|
||||
char[] str8 = dict.add(str3);
|
||||
assertSame(str4, str8);
|
||||
|
||||
char[] str9 = dict.add(str1);
|
||||
assertNotSame(str2, str9);
|
||||
|
||||
// This should be the same since the removals are done by addition time,
|
||||
// not access time
|
||||
char[] str10 = dict.add(str6);
|
||||
assertSame(str7, str10);
|
||||
}
|
||||
|
||||
public void testMapAdd() {
|
||||
CharArrayMap map = new CharArrayMap(4);
|
||||
char[] key1 = "key1".toCharArray();
|
||||
Object value1 = new Integer(43);
|
||||
map.put(key1, value1);
|
||||
|
||||
char[] key2 = "key1".toCharArray();
|
||||
Object value2 = map.get(key2);
|
||||
assertEquals(value1, value2);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
map.put(("ikey" + i).toCharArray(), new Integer(i));
|
||||
}
|
||||
|
||||
Object ivalue1 = map.get("ikey1".toCharArray());
|
||||
assertEquals(ivalue1, new Integer(1));
|
||||
|
||||
Object ivalue4 = map.get("ikey4".toCharArray());
|
||||
assertEquals(ivalue4, new Integer(4));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Created on May 28, 2004
|
||||
*
|
||||
* TODO To change the template for this generated file go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
package org.eclipse.cdt.core.parser;
|
||||
|
||||
/**
|
||||
* @author dschaefe
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public class CharArrayMap {
|
||||
|
||||
private char[][] keyTable;
|
||||
private Object[] valueTable;
|
||||
private int[] hashTable;
|
||||
private int[] nextTable;
|
||||
|
||||
private int currEntry;
|
||||
|
||||
public CharArrayMap(int initialSize) {
|
||||
// Make sure size is a power of two
|
||||
int size = 1;
|
||||
while (size < initialSize)
|
||||
size <<= 1;
|
||||
createTables(size);
|
||||
}
|
||||
|
||||
private final void createTables(int size) {
|
||||
keyTable = new char[size][];
|
||||
valueTable = new Object[size];
|
||||
nextTable = new int[size];
|
||||
hashTable = new int[size << 1];
|
||||
currEntry = 0;
|
||||
}
|
||||
|
||||
private final int hash(char[] key) {
|
||||
return CharArrayUtils.hash(key) & (hashTable.length - 1);
|
||||
}
|
||||
|
||||
private final int add(char[] key, Object value) {
|
||||
keyTable[currEntry] = key;
|
||||
valueTable[currEntry] = value;
|
||||
return ++currEntry;
|
||||
}
|
||||
|
||||
// returns the overwritten object if there was one
|
||||
public Object put(char[] key, Object value) {
|
||||
try {
|
||||
int hash = hash(key);
|
||||
int i = hashTable[hash] - 1;
|
||||
if (i < 0) {
|
||||
// Nobody here
|
||||
hashTable[hash] = add(key, value);
|
||||
} else {
|
||||
// See if the key is already defined
|
||||
int last = i;
|
||||
while (i >= 0) {
|
||||
if (CharArrayUtils.equals(key, keyTable[i])) {
|
||||
Object oldvalue = valueTable[i];
|
||||
valueTable[i] = value;
|
||||
// Nothing left to do, escape...
|
||||
return oldvalue;
|
||||
}
|
||||
last = i;
|
||||
i = nextTable[i] - 1;
|
||||
}
|
||||
|
||||
// Not there, time to add
|
||||
nextTable[last] = add(key, value);
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// Oops, too many, resize and try again
|
||||
char[][] oldKeyTable = keyTable;
|
||||
Object[] oldValueTable = valueTable;
|
||||
|
||||
int newSize = hashTable.length << 1;
|
||||
createTables(newSize);
|
||||
for (int i = 0; i < oldKeyTable.length; ++i)
|
||||
put(oldKeyTable[i], oldValueTable[i]);
|
||||
|
||||
return put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(char[] key) {
|
||||
int hash = hash(key);
|
||||
int i = hashTable[hash] - 1;
|
||||
while (i >= 0) {
|
||||
if (CharArrayUtils.equals(key, keyTable[i]))
|
||||
return valueTable[i];
|
||||
i = nextTable[i] - 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Created on May 28, 2004
|
||||
*
|
||||
* TODO To change the template for this generated file go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
package org.eclipse.cdt.core.parser;
|
||||
|
||||
/**
|
||||
* @author dschaefe
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public class CharArrayPool {
|
||||
|
||||
private int currEntry = -1;
|
||||
|
||||
// Hash table is twice the size of the others
|
||||
private int[] hashTable;
|
||||
private int[] nextTable;
|
||||
private char[][] stringTable;
|
||||
|
||||
public CharArrayPool(int tableSize) {
|
||||
// make sure size is a power of 2
|
||||
int size = 1;
|
||||
while (size < tableSize)
|
||||
size <<= 1;
|
||||
|
||||
hashTable = new int[size << 1];
|
||||
nextTable = new int[tableSize];
|
||||
stringTable = new char[tableSize][];
|
||||
}
|
||||
|
||||
private final int hash(char[] source, int start, int length) {
|
||||
return CharArrayUtils.hash(source, start, length) & (hashTable.length - 1);
|
||||
}
|
||||
|
||||
private static final boolean equals(char[] str1, int start, int length, char[] str2) {
|
||||
if (str2.length != length)
|
||||
return false;
|
||||
|
||||
int curr = start;
|
||||
for (int i = 0; i < length; ++i)
|
||||
if (str1[curr++] != str2[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private final char[] find(char[] source, int start, int length, int hash) {
|
||||
int i = hashTable[hash] - 1;
|
||||
|
||||
do {
|
||||
char[] str = stringTable[i];
|
||||
if (equals(source, start, length, str))
|
||||
return str;
|
||||
i = nextTable[i] - 1;
|
||||
} while (i >= 0);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Removes the current entry
|
||||
private final void remove() {
|
||||
int hash = hash(stringTable[currEntry], 0, stringTable[currEntry].length);
|
||||
int i = hashTable[hash] - 1;
|
||||
if (i == currEntry)
|
||||
// make my next the hash entry
|
||||
hashTable[hash] = nextTable[currEntry];
|
||||
else {
|
||||
// remove me from the next list
|
||||
int last;
|
||||
do {
|
||||
last = i;
|
||||
i = nextTable[i] - 1;
|
||||
} while (i != currEntry);
|
||||
|
||||
nextTable[last] = nextTable[currEntry];
|
||||
}
|
||||
|
||||
stringTable[currEntry] = null;
|
||||
nextTable[currEntry] = 0;
|
||||
}
|
||||
|
||||
private final void addHashed(char[] str, int hash) {
|
||||
// First remove the existing string if there is one
|
||||
if (++currEntry == stringTable.length)
|
||||
currEntry = 0;
|
||||
|
||||
if (stringTable[currEntry] != null)
|
||||
remove();
|
||||
|
||||
stringTable[currEntry] = str;
|
||||
|
||||
// Now add it to the hash table, insert into next entries as necessary
|
||||
if (hashTable[hash] != 0)
|
||||
nextTable[currEntry] = hashTable[hash];
|
||||
hashTable[hash] = currEntry + 1;
|
||||
}
|
||||
|
||||
public final char[] add(char[] source, int start, int length) {
|
||||
// do we have it already?
|
||||
int hash = hash(source, start, length);
|
||||
char[] result = null;
|
||||
if (hashTable[hash] > 0)
|
||||
result = find(source, start, length, hash);
|
||||
|
||||
// if not, add it
|
||||
if (result == null) {
|
||||
System.arraycopy(source, 0, result = new char[length], 0, length);
|
||||
addHashed(result, hash);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public final char[] add(char[] source) {
|
||||
return add(source, 0, source.length);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Created on May 28, 2004
|
||||
*
|
||||
* TODO To change the template for this generated file go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
package org.eclipse.cdt.core.parser;
|
||||
|
||||
/**
|
||||
* @author dschaefe
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public class CharArrayUtils {
|
||||
|
||||
public static final int hash(char[] str, int start, int length) {
|
||||
int h = 0;
|
||||
|
||||
int curr = start;
|
||||
for (int i = length; i > 0; --i, curr++)
|
||||
h += str[curr];
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
public static final int hash(char[] str) {
|
||||
return hash(str, 0, str.length);
|
||||
}
|
||||
|
||||
public static final boolean equals(char[] str1, char[] str2) {
|
||||
if (str1 == str2)
|
||||
return true;
|
||||
|
||||
if (str1 == null || str2 == null)
|
||||
return false;
|
||||
|
||||
if (str1.length != str2.length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < str1.length; ++i)
|
||||
if (str1[i] != str2[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue