diff --git a/src/core/org/luaj/lib/TableLib.java b/src/core/org/luaj/lib/TableLib.java index 08f522b4..fc7f624b 100644 --- a/src/core/org/luaj/lib/TableLib.java +++ b/src/core/org/luaj/lib/TableLib.java @@ -36,6 +36,8 @@ public class TableLib extends LFunction { public static final String[] NAMES = { "table", "concat", + "foreach", + "foreachi", "getn", "insert", "maxn", @@ -43,13 +45,15 @@ public class TableLib extends LFunction { "sort", }; - private static final int INSTALL = 0; - private static final int CONCAT = 1; - private static final int GETN = 2; - private static final int INSERT = 3; - private static final int MAXN = 4; - private static final int REMOVE = 5; - private static final int SORT = 6; + private static final int INSTALL = 0; + private static final int CONCAT = 1; + private static final int FOREACH = 2; + private static final int FOREACHI = 3; + private static final int GETN = 4; + private static final int INSERT = 5; + private static final int MAXN = 6; + private static final int REMOVE = 7; + private static final int SORT = 8; public static void install( LTable globals ) { LTable table = new LTable(); @@ -117,6 +121,21 @@ public class TableLib extends LFunction { break; } + /* table.getn (table) + * + * Get length of table t. + */ + case FOREACH: + case FOREACHI: + { + LTable table = vm.totable(2); + LFunction function = vm.tojavafunction(3); + LValue result = table.foreach( vm, function, id==FOREACHI ); + vm.resettop(); + vm.pushlvalue( result ); + break; + } + /* table.getn (table) * * Get length of table t. diff --git a/src/core/org/luaj/vm/LTable.java b/src/core/org/luaj/vm/LTable.java index e9066d78..373f9704 100644 --- a/src/core/org/luaj/vm/LTable.java +++ b/src/core/org/luaj/vm/LTable.java @@ -700,4 +700,45 @@ public class LTable extends LValue { return n + slot + 1; } + + + /** + * Executes the given f over all elements of table. For each element, f is + * called with the index and respective value as arguments. If f returns a + * non-nil value, then the loop is broken, and this value is returned as the + * final value of foreach. + * + * @param vm + * @param function + * @param isforeachi is a table.foreachi() call, not a table.foreach() call + * @return + */ + public LValue foreach(LuaState vm, LFunction function, boolean isforeachi) { + for ( int i = 0; i < m_vector.length; ++i ) { + if ( m_vector[ i ] != LNil.NIL ) { + if ( foreachitem( vm, function, LInteger.valueOf(i+1), m_vector[i] ) ) + return vm.topointer(1); + } + } + + if ( (! isforeachi) && m_hashKeys != null ) { + for ( int i = 0; i < m_hashKeys.length; ++i ) { + if ( m_hashKeys[ i ] != null ) { + if ( foreachitem( vm, function, m_hashKeys[i], m_hashValues[i] ) ) + return vm.topointer(1); + } + } + } + + return LNil.NIL; + } + + private static boolean foreachitem(LuaState vm, LFunction f, LValue key, LValue value) { + vm.resettop(); + vm.pushlvalue( f ); + vm.pushlvalue( key ); + vm.pushlvalue( value ); + vm.call(2, 1); + return ! vm.isnil(1); + } } diff --git a/src/test/res/table.lua b/src/test/res/table.lua index 2ffb8e31..2f479155 100644 --- a/src/test/res/table.lua +++ b/src/test/res/table.lua @@ -66,3 +66,36 @@ table.sort(t) print( table.concat(t,'-'), table.maxn(t), #t ) table.sort(t,function(a,b) return b