New implementation for Lua tables. Does not use Vector or Hashtable, instead

uses plain Java arrays directly to keep heap allocation to a minimum.
Includes some unit tests that seem to indicate the basic operations are
correct. However, the following things are not implemented:

* Shrinking the capacity when elements are removed
* Optimal storage of each element in array vs. hash when entries are
  added out of order. A junit test case is there for this.
This commit is contained in:
Ian Farmer
2007-09-03 00:38:38 +00:00
parent 79d5642bfd
commit b8571b93f9
8 changed files with 629 additions and 174 deletions

View File

@@ -78,7 +78,7 @@ public class StandardTest extends TestCase {
// relies on weak tables having their elements removed by
// the garbage collector. Until we implement that, remove the
// built-in collectgarbage function.
GlobalState.getGlobalsTable().rawSet( new LString("collectgarbage"), LNil.NIL );
GlobalState.getGlobalsTable().put( "collectgarbage", LNil.NIL );
StackState state = new StackState();
Closure c = new Closure( state, code );

View File

@@ -0,0 +1,137 @@
package lua.value;
import junit.framework.TestCase;
public class LTableTest extends TestCase {
public void testInOrderIntegerKeyInsertion() {
LTable t = new LTable();
for ( int i = 1; i <= 32; ++i ) {
t.put( i, new LString( "Test Value! "+i ) );
}
// Ensure capacities make sense
assertEquals( 0, t.getHashCapacity() );
assertTrue( t.getArrayCapacity() >= 32 );
assertTrue( t.getArrayCapacity() <= 64 );
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! " + i, t.get( i ).luaAsString() );
}
}
public void testOutOfOrderIntegerKeyInsertion() {
LTable t = new LTable();
for ( int i = 32; i > 0; --i ) {
t.put( i, new LString( "Test Value! "+i ) );
}
// Ensure capacities make sense
assertEquals( 0, t.getHashCapacity() );
assertTrue( t.getArrayCapacity() >= 32 );
assertTrue( t.getArrayCapacity() <= 64 );
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! " + i, t.get( i ).luaAsString() );
}
}
public void testStringAndIntegerKeys() {
LTable t = new LTable();
for ( int i = 0; i < 10; ++i ) {
LString str = new LString( String.valueOf( i ) );
t.put( i, str );
t.put( str, new LInteger( i ) );
}
assertTrue( t.getArrayCapacity() >= 9 ); // 1, 2, ..., 9
assertTrue( t.getArrayCapacity() <= 18 );
assertTrue( t.getHashCapacity() >= 11 ); // 0, "0", "1", ..., "9"
assertTrue( t.getHashCapacity() <= 33 );
LValue[] keys = t.getKeys();
int intKeys = 0;
int stringKeys = 0;
assertEquals( 20, keys.length );
for ( int i = 0; i < keys.length; ++i ) {
LValue k = keys[i];
if ( k instanceof LInteger ) {
final int ik = k.luaAsInt();
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( ( intKeys & mask ) == 0 );
intKeys |= mask;
} else if ( k instanceof LString ) {
final int ik = Integer.parseInt( k.luaAsString() );
assertEquals( String.valueOf( ik ), k.luaAsString() );
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 );
stringKeys |= mask;
} else {
fail( "Unexpected type of key found" );
}
}
assertEquals( 0x03FF, intKeys );
assertEquals( 0x03FF, stringKeys );
}
public void testBadInitialCapacity() {
LTable t = new LTable(0, 1);
t.put( "test", new LString("foo") );
t.put( "explode", new LString("explode") );
assertEquals( 2, t.size() );
}
public void testRemove1() {
LTable t = new LTable(0, 1);
t.put( "test", new LString("foo") );
t.put( "explode", LNil.NIL );
t.put( 42, LNil.NIL );
t.put( new LTable(), LNil.NIL );
t.put( "test", LNil.NIL );
assertEquals( 0, t.size() );
t.put( 10, new LInteger( 5 ) );
t.put( 10, LNil.NIL );
assertEquals( 0, t.size() );
}
public void testRemove2() {
LTable t = new LTable(0, 1);
t.put( "test", new LString("foo") );
t.put( "string", new LInteger( 10 ) );
assertEquals( 2, t.size() );
t.put( "string", LNil.NIL );
t.put( "three", new LDouble( 3.14 ) );
assertEquals( 2, t.size() );
t.put( "test", LNil.NIL );
assertEquals( 1, t.size() );
t.put( 10, new LInteger( 5 ) );
assertEquals( 2, t.size() );
t.put( 10, LNil.NIL );
assertEquals( 1, t.size() );
t.put( "three", LNil.NIL );
assertEquals( 0, t.size() );
}
}