Table unit tests and implementation of table.remove(), table.sort()

This commit is contained in:
James Roseborough
2007-10-31 23:24:51 +00:00
parent facb8d1d07
commit 434530b60f
7 changed files with 137 additions and 32 deletions

View File

@@ -663,24 +663,26 @@ public class LuaCompat extends LFunction {
* If i is greater than j, returns the empty string. * If i is greater than j, returns the empty string.
*/ */
private void concat(VM vm) { private void concat(VM vm) {
LTable table = (LTable) vm.getArg(0); int n = vm.gettop();
LString sep = vm.getArgAsLuaString(1); LTable table = vm.totable(2);
int i = vm.getArgAsInt(2); LString sep = (n>2? vm.tolstring(3): null);
int j = vm.getArgAsInt(3); int i = vm.tointeger(4);
LValue[] keys = table.getKeys(); int j = vm.tointeger(5);
int len = table.luaLength();
if ( i == 0 ) if ( i == 0 )
i = 1; i = 1;
if ( j == 0 ) if ( j == 0 )
j = keys.length; j = len;
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
for ( int k=i; k<=j; k++ ) { for ( int k=i; k<=j; k++ ) {
LValue v = table.get(keys[k-1]); LValue v = table.get(k);
v.luaAsString().write(baos); v.luaAsString().write(baos);
if ( k<j ) if ( k<j && sep!=null )
sep.write( baos ); sep.write( baos );
} }
vm.setResult( new LString( baos.toByteArray() ) ); vm.settop(0);
vm.pushlstring( baos.toByteArray() );
} catch (IOException e) { } catch (IOException e) {
vm.error(e.getMessage()); vm.error(e.getMessage());
} }
@@ -693,10 +695,10 @@ public class LuaCompat extends LFunction {
* table.insert(t,x) inserts x at the end of table t. * table.insert(t,x) inserts x at the end of table t.
*/ */
private void insert(VM vm) { private void insert(VM vm) {
int n = vm.getArgCount(); int n = vm.gettop();
LTable table = (LTable) vm.getArg(0); LTable table = vm.totable(2);
int pos = (n>2? vm.getArgAsInt(1): 0); int pos = (n>3? vm.tointeger(3): 0);
LValue value = vm.getArg(n-1); LValue value = vm.topointer(-1);
table.luaInsertPos( pos, value ); table.luaInsertPos( pos, value );
} }
@@ -707,8 +709,9 @@ public class LuaCompat extends LFunction {
* indices. (To do its job this function does a linear traversal of the whole table.) * indices. (To do its job this function does a linear traversal of the whole table.)
*/ */
private void maxn(VM vm) { private void maxn(VM vm) {
LTable table = (LTable) vm.getArg(0); LTable table = vm.totable(2);
vm.setResult( LInteger.valueOf( table.luaMaxN() ) ); vm.settop(0);
vm.pushinteger( table.luaMaxN() );
} }
@@ -719,9 +722,9 @@ public class LuaCompat extends LFunction {
* so that a call table.remove(t) removes the last element of table t. * so that a call table.remove(t) removes the last element of table t.
*/ */
private void remove(VM vm) { private void remove(VM vm) {
int n = vm.getArgCount(); int n = vm.gettop();
LTable table = (LTable) vm.getArg(0); LTable table = vm.totable(2);
int pos = (n>1? vm.getArgAsInt(1): 0); int pos = (n>1? vm.tointeger(3): 0);
table.luaRemovePos( pos ); table.luaRemovePos( pos );
} }
@@ -735,7 +738,8 @@ public class LuaCompat extends LFunction {
* The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort. * The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
*/ */
private void sort(VM vm) { private void sort(VM vm) {
LTable table = (LTable) vm.getArg(0); LTable table = vm.totable(2);
table.luaSort(); LValue compare = vm.topointer(3);
table.luaSort( vm, compare );
} }
} }

View File

@@ -1011,6 +1011,10 @@ public class StackState extends Lua implements VM {
pushlvalue(new LString(bytes, offset, length)); pushlvalue(new LString(bytes, offset, length));
} }
public void pushlstring(byte[] byteArray) {
pushlstring(byteArray, 0, byteArray.length);
}
public void pushnil() { public void pushnil() {
pushlvalue(LNil.NIL); pushlvalue(LNil.NIL);
} }

View File

@@ -4,6 +4,7 @@ import java.io.InputStream;
import lua.io.Closure; import lua.io.Closure;
import lua.value.LString; import lua.value.LString;
import lua.value.LTable;
import lua.value.LValue; import lua.value.LValue;
/** /**
* <hr> * <hr>
@@ -938,6 +939,14 @@ public interface VM {
*/ */
public void pushlstring(byte[] bytes, int offset, int length); public void pushlstring(byte[] bytes, int offset, int length);
/**
* Push string bytes onto the stack as a string. <span class="apii">[-0, +1,
* <em>m</em>]</span>
*
* Pushes the bytes in byteArray onto the stack as a lua string.
*/
public void pushlstring(byte[] byteArray);
/** /**
* Push an LValue onto the stack. <span class="apii">[-0, +1, * Push an LValue onto the stack. <span class="apii">[-0, +1,
* <em>m</em>]</span> * <em>m</em>]</span>
@@ -1341,6 +1350,15 @@ public interface VM {
*/ */
public StackState tothread(int index); public StackState tothread(int index);
/**
* Get a value from the stack as a lua table. <span class="apii">[-0, +0, <em>-</em>]</span>
*
* <p>
* Converts the value at the given acceptable index to a Lua table
* This value must be a table otherwise, the function returns <code>NIL</code>.
*/
public LTable totable(int index);
/** /**
* Get the Object from a userdata value. <span class="apii">[-0, +0, * Get the Object from a userdata value. <span class="apii">[-0, +0,
* <em>-</em>]</span> * <em>-</em>]</span>

View File

@@ -1,5 +1,7 @@
package lua.value; package lua.value;
import java.util.Arrays;
import lua.Lua; import lua.Lua;
import lua.VM; import lua.VM;
@@ -513,25 +515,98 @@ public class LTable extends LValue {
return m_vector.length; return m_vector.length;
} }
/* /**
* Insert element at a position in the list.
* @pos index to insert at, or 0 to insert at end. * @pos index to insert at, or 0 to insert at end.
*/ */
public void luaInsertPos(int pos, LValue value) { public void luaInsertPos(int pos, LValue value) {
if ( pos != 0 ) if ( pos > m_arrayEntries + 1 )
throw new RuntimeException("luaInsertPos() not implemented"); put( pos, value );
put( m_arrayEntries + m_hashEntries + 1, value ); else {
} final int index = Math.max(0,pos==0? m_arrayEntries: pos-1);
if ( m_arrayEntries + 1 > m_vector.length )
public void luaSort() { resize( ( m_arrayEntries + 1 ) * 2 );
throw new RuntimeException("luaSort() not implemented"); if ( m_vector[index] != LNil.NIL ) {
System.arraycopy(m_vector, index, m_vector, index+1, m_vector.length-1-index);
}
m_vector[index] = value;
++m_arrayEntries;
}
} }
/**
* Remove an element from the list part of the table
* @param pos position to remove, or 0 to remove last element
*/
public void luaRemovePos(int pos) { public void luaRemovePos(int pos) {
throw new RuntimeException("luaRemovePos() not implemented"); if ( pos > m_arrayEntries ) {
put( pos, LNil.NIL );
} else {
final int index = Math.max(0,pos<=0? m_arrayEntries: pos)-1;
if ( index < 0 )
return;
System.arraycopy(m_vector, index+1, m_vector, index, m_vector.length-1-index);
m_vector[m_vector.length-1] = LNil.NIL;
--m_arrayEntries;
}
} }
public int luaMaxN() { public int luaMaxN() {
throw new RuntimeException("luaMaxN() not implemented"); return m_arrayEntries;
}
// ----------------- sort support -----------------------------
//
// implemented heap sort from wikipedia
//
public void luaSort(VM vm, LValue compare) {
heapSort(m_arrayEntries, vm, compare);
}
private void heapSort(int count, VM vm, LValue cmpfunc) {
heapify(count, vm, cmpfunc);
for ( int end=count-1; end>0; ) {
swap(end, 0);
siftDown(0, --end, vm, cmpfunc);
}
}
private void heapify(int count, VM vm, LValue cmpfunc) {
for ( int start=count/2-1; start>=0; --start )
siftDown(start, count - 1, vm, cmpfunc);
}
private void siftDown(int start, int end, VM vm, LValue cmpfunc) {
for ( int root=start; root*2+1 <= end; ) {
int child = root*2+1;
if (child < end && compare(child, child + 1, vm, cmpfunc))
++child;
if (compare(root, child, vm, cmpfunc)) {
swap(root, child);
root = child;
} else
return;
}
}
private boolean compare(int i, int j, VM vm, LValue cmpfunc) {
if ( cmpfunc != LNil.NIL ) {
vm.pushlvalue(cmpfunc);
vm.pushlvalue(m_vector[i]);
vm.pushlvalue(m_vector[j]);
vm.call(2, 1);
boolean result = vm.toboolean(1);
vm.settop(0);
return result;
} else {
return m_vector[j].luaBinCmpUnknown( Lua.OP_LT, m_vector[i] );
}
}
private void swap(int i, int j) {
LValue tmp = m_vector[i];
m_vector[i] = m_vector[j];
m_vector[j] = tmp;
} }
} }

View File

@@ -30,7 +30,7 @@ public class LuacRunner {
LuaJava.install(); LuaJava.install();
// new lua state // new lua state
StackState state = new DebugStackState(); StackState state = new StackState();
VM vm = state; VM vm = state;
// load the file // load the file

View File

@@ -96,6 +96,10 @@ public class LuaJTest extends TestCase {
runTest( "strlib" ); runTest( "strlib" );
} }
public void testTable() throws IOException, InterruptedException {
runTest( "table" );
}
public void testType() throws IOException, InterruptedException { public void testType() throws IOException, InterruptedException {
runTest( "type" ); runTest( "type" );
} }
@@ -120,7 +124,7 @@ public class LuaJTest extends TestCase {
LuaCompat.install(); LuaCompat.install();
// new lua state // new lua state
StackState state = new DebugStackState(); StackState state = new StackState();
// load the file // load the file
Proto p = loadScriptResource( state, testName ); Proto p = loadScriptResource( state, testName );

BIN
src/test/res/table.luac Normal file

Binary file not shown.