From 434530b60fe70e85e76df8dcf277923ce6ce376d Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 31 Oct 2007 23:24:51 +0000 Subject: [PATCH] Table unit tests and implementation of table.remove(), table.sort() --- .../java/lua/addon/luacompat/LuaCompat.java | 44 ++++---- src/main/java/lua/StackState.java | 4 + src/main/java/lua/VM.java | 18 ++++ src/main/java/lua/value/LTable.java | 95 ++++++++++++++++-- src/test/java/LuacRunner.java | 2 +- src/test/java/lua/LuaJTest.java | 6 +- src/test/res/table.luac | Bin 0 -> 4741 bytes 7 files changed, 137 insertions(+), 32 deletions(-) create mode 100644 src/test/res/table.luac diff --git a/src/addon/java/lua/addon/luacompat/LuaCompat.java b/src/addon/java/lua/addon/luacompat/LuaCompat.java index 5eaf2b26..376a4a93 100644 --- a/src/addon/java/lua/addon/luacompat/LuaCompat.java +++ b/src/addon/java/lua/addon/luacompat/LuaCompat.java @@ -663,24 +663,26 @@ public class LuaCompat extends LFunction { * If i is greater than j, returns the empty string. */ private void concat(VM vm) { - LTable table = (LTable) vm.getArg(0); - LString sep = vm.getArgAsLuaString(1); - int i = vm.getArgAsInt(2); - int j = vm.getArgAsInt(3); - LValue[] keys = table.getKeys(); + int n = vm.gettop(); + LTable table = vm.totable(2); + LString sep = (n>2? vm.tolstring(3): null); + int i = vm.tointeger(4); + int j = vm.tointeger(5); + int len = table.luaLength(); if ( i == 0 ) i = 1; if ( j == 0 ) - j = keys.length; + j = len; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { for ( int k=i; k<=j; k++ ) { - LValue v = table.get(keys[k-1]); + LValue v = table.get(k); v.luaAsString().write(baos); - if ( k2? vm.getArgAsInt(1): 0); - LValue value = vm.getArg(n-1); + int n = vm.gettop(); + LTable table = vm.totable(2); + int pos = (n>3? vm.tointeger(3): 0); + LValue value = vm.topointer(-1); 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.) */ private void maxn(VM vm) { - LTable table = (LTable) vm.getArg(0); - vm.setResult( LInteger.valueOf( table.luaMaxN() ) ); + LTable table = vm.totable(2); + 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. */ private void remove(VM vm) { - int n = vm.getArgCount(); - LTable table = (LTable) vm.getArg(0); - int pos = (n>1? vm.getArgAsInt(1): 0); + int n = vm.gettop(); + LTable table = vm.totable(2); + int pos = (n>1? vm.tointeger(3): 0); 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. */ private void sort(VM vm) { - LTable table = (LTable) vm.getArg(0); - table.luaSort(); + LTable table = vm.totable(2); + LValue compare = vm.topointer(3); + table.luaSort( vm, compare ); } } diff --git a/src/main/java/lua/StackState.java b/src/main/java/lua/StackState.java index 0f1450ba..0b9d065c 100644 --- a/src/main/java/lua/StackState.java +++ b/src/main/java/lua/StackState.java @@ -1011,6 +1011,10 @@ public class StackState extends Lua implements VM { pushlvalue(new LString(bytes, offset, length)); } + public void pushlstring(byte[] byteArray) { + pushlstring(byteArray, 0, byteArray.length); + } + public void pushnil() { pushlvalue(LNil.NIL); } diff --git a/src/main/java/lua/VM.java b/src/main/java/lua/VM.java index 8e8bee52..0ccb3846 100644 --- a/src/main/java/lua/VM.java +++ b/src/main/java/lua/VM.java @@ -4,6 +4,7 @@ import java.io.InputStream; import lua.io.Closure; import lua.value.LString; +import lua.value.LTable; import lua.value.LValue; /** *
@@ -938,6 +939,14 @@ public interface VM { */ public void pushlstring(byte[] bytes, int offset, int length); + /** + * Push string bytes onto the stack as a string. [-0, +1, + * m] + * + * Pushes the bytes in byteArray onto the stack as a lua string. + */ + public void pushlstring(byte[] byteArray); + /** * Push an LValue onto the stack. [-0, +1, * m] @@ -1341,6 +1350,15 @@ public interface VM { */ public StackState tothread(int index); + /** + * Get a value from the stack as a lua table. [-0, +0, -] + * + *

+ * Converts the value at the given acceptable index to a Lua table + * This value must be a table otherwise, the function returns NIL. + */ + public LTable totable(int index); + /** * Get the Object from a userdata value. [-0, +0, * -] diff --git a/src/main/java/lua/value/LTable.java b/src/main/java/lua/value/LTable.java index d15133a0..9de86cbd 100644 --- a/src/main/java/lua/value/LTable.java +++ b/src/main/java/lua/value/LTable.java @@ -1,5 +1,7 @@ package lua.value; +import java.util.Arrays; + import lua.Lua; import lua.VM; @@ -513,25 +515,98 @@ public class LTable extends LValue { return m_vector.length; } - /* + /** + * Insert element at a position in the list. * @pos index to insert at, or 0 to insert at end. */ public void luaInsertPos(int pos, LValue value) { - if ( pos != 0 ) - throw new RuntimeException("luaInsertPos() not implemented"); - put( m_arrayEntries + m_hashEntries + 1, value ); - } - - public void luaSort() { - throw new RuntimeException("luaSort() not implemented"); + if ( pos > m_arrayEntries + 1 ) + put( pos, value ); + else { + final int index = Math.max(0,pos==0? m_arrayEntries: pos-1); + if ( m_arrayEntries + 1 > m_vector.length ) + resize( ( m_arrayEntries + 1 ) * 2 ); + 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) { - 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() { - 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; } } diff --git a/src/test/java/LuacRunner.java b/src/test/java/LuacRunner.java index f247ed2b..3a6c7536 100644 --- a/src/test/java/LuacRunner.java +++ b/src/test/java/LuacRunner.java @@ -30,7 +30,7 @@ public class LuacRunner { LuaJava.install(); // new lua state - StackState state = new DebugStackState(); + StackState state = new StackState(); VM vm = state; // load the file diff --git a/src/test/java/lua/LuaJTest.java b/src/test/java/lua/LuaJTest.java index 2b7edbd2..c1ec49cc 100644 --- a/src/test/java/lua/LuaJTest.java +++ b/src/test/java/lua/LuaJTest.java @@ -96,6 +96,10 @@ public class LuaJTest extends TestCase { runTest( "strlib" ); } + public void testTable() throws IOException, InterruptedException { + runTest( "table" ); + } + public void testType() throws IOException, InterruptedException { runTest( "type" ); } @@ -120,7 +124,7 @@ public class LuaJTest extends TestCase { LuaCompat.install(); // new lua state - StackState state = new DebugStackState(); + StackState state = new StackState(); // load the file Proto p = loadScriptResource( state, testName ); diff --git a/src/test/res/table.luac b/src/test/res/table.luac new file mode 100644 index 0000000000000000000000000000000000000000..91b14f2e2ab89781cefd22f84dc632e378ced544 GIT binary patch literal 4741 zcmc&%TW=dh6h32bV>@x7K)5y(QzCJT%l#s5olV+E8}$L+c;ErsS*WGfuI#nrZMUq&BoKw&NTaglBL==-C;R^C1_X|(1f9XZ* z`&Fp~^EHoDW|-%SEQM~Cz{zNza>%DV?8l2XzVhU`uLr*Lyu9I2e8ZFOO^<%L>B)_6 z2J>X%)G?9&2Wmzx4K65#?JC?$S{?pAaQ z$r1gfNG#+2iKNVV=r`#%QsBli2i*~Us2quy{jl#N#6o%WA%Ao~3Vz~y;D-u`r!Z$c zMAyk<+q?aVHpL&P&jEVD_diJqTl-My=ZGx|v!m8p?4rg$=g5=ZcZqeHC3JGGx<|k3 zHE<}#Noxp83tT)4>!)uUqxUw4scUeQJuM#1UZ$`|-4}%JiFpTX4(RjDIgIn6?m--L z`@r51@$*Sc+tcP=D|9>ET0x!cezQg7gmQ^uwS@O_iCj^{{#m3rEMiR;$;}+cUP{jY z5u4cyO>TcH-XGKNg{M%NHwZ~C;O9!K-U!G!0kK>z)tZf3B`5`cJ7|-$2xZXPHA-@j zFf|*#5rUnjaS&W=`OsxBSus>!1%1$Y4xRgx9?-yaJIK0 zuucDQKAwS%1J{RFr4c^0!WAnhD|~xZI*)*hjOvZH-wM`Bmn*%7&5QHa$1gcKh&Dfd zT-n6KY%^)>O;GK6uO9^6IjgJJ_Pc(=>P|?l^Xs2q46JTN>P#DT)XjuVt5R1ofT1mW z%fH<0`Zhd{$!M%eUiNL5t#Icj=ROX%TxvI4gNAWYd2GVn+uJk3?(VJ;dcB?zc6N4* z(Cv1O(CKuH5CnbmcDrq#ukQso$I+a74mZ7hOB@+W>LdIBGiIwL+8@%37{`Y`HvVlR zgdi86F|f^ywC&G_nxn>ZLV?$l{TL1}Z!Y2R@*dN1u4)-A=gzMUlC?EnMj}LR<1s+$3ItZdSYuZW6CRmjrNQgqC&Ax&Y49faNxTJJ z8oUF(#k-KF;XQED;C=9i@d3tZa2EVoA;C=p7yMzYW1I%bGlj?J=74}r1_|v GT>k*WAwv%U literal 0 HcmV?d00001