Fix weak tables, improve unit test
This commit is contained in:
@@ -28,7 +28,6 @@ import org.luaj.vm.LFunction;
|
||||
import org.luaj.vm.LString;
|
||||
import org.luaj.vm.LTable;
|
||||
import org.luaj.vm.LValue;
|
||||
import org.luaj.vm.LWeakTable;
|
||||
import org.luaj.vm.LuaState;
|
||||
|
||||
|
||||
@@ -186,7 +185,9 @@ public class TableLib extends LFunction {
|
||||
LTable table = vm.totable(2);
|
||||
int pos = (n>=3? vm.tointeger(3): 0);
|
||||
vm.resettop();
|
||||
vm.pushlvalue( table.luaRemovePos( pos ) );
|
||||
LValue v = table.luaRemovePos(pos);
|
||||
if ( ! v.isNil() )
|
||||
vm.pushlvalue( v );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ import org.luaj.vm.LuaState;
|
||||
*/
|
||||
public class LTable extends LValue {
|
||||
|
||||
private Object[] array;
|
||||
private LValue[] hashKeys;
|
||||
protected Object[] array;
|
||||
protected LValue[] hashKeys;
|
||||
private Object[] hashValues;
|
||||
private int hashEntries;
|
||||
private LTable m_metatable;
|
||||
@@ -70,7 +70,8 @@ public class LTable extends LValue {
|
||||
* in the range 1 .. narray and nhash non-integer keys.
|
||||
*/
|
||||
public LTable( int narray, int nhash ) {
|
||||
nhash = Math.max(nhash,MIN_HASH_CAPACITY);
|
||||
if ( nhash > 0 && nhash < MIN_HASH_CAPACITY )
|
||||
nhash = MIN_HASH_CAPACITY;
|
||||
array = new Object[narray];
|
||||
hashKeys = new LValue[nhash];
|
||||
hashValues = new Object[nhash];
|
||||
@@ -205,9 +206,8 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the table contains an entry with the given key, false if
|
||||
* not. Ignores the metatable.
|
||||
*
|
||||
* Return true if the table contains an entry with the given key,
|
||||
* false if not. Ignores the metatable.
|
||||
*/
|
||||
public boolean containsKey( LValue key ) {
|
||||
if ( key.isInteger() ) {
|
||||
@@ -218,11 +218,14 @@ public class LTable extends LValue {
|
||||
return null != hashGet(key);
|
||||
}
|
||||
|
||||
/** Check if a integer-valued key exists */
|
||||
/**
|
||||
* Return true if the table contains an entry with the given integer-valued key,
|
||||
* false if not. Ignores the metatable.
|
||||
*/
|
||||
public boolean containsKey( int key ) {
|
||||
return null != (key>0 && key<=array.length?
|
||||
array[key-1]:
|
||||
hashGet(LInteger.valueOf(key)) );
|
||||
return (key>0 && key<=array.length?
|
||||
array[key-1] != null:
|
||||
(hashKeys.length>0 && hashKeys[hashFindSlot(LInteger.valueOf(key))]!=null));
|
||||
}
|
||||
|
||||
|
||||
@@ -244,9 +247,9 @@ public class LTable extends LValue {
|
||||
|
||||
private static final int MAX_KEY = 0x3fffffff;
|
||||
|
||||
/*
|
||||
** Try to find a boundary in table `t'. A `boundary' is an integer index
|
||||
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
|
||||
/**
|
||||
* Try to find a boundary in table `t'. A `boundary' is an integer index
|
||||
* such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
|
||||
*/
|
||||
public int luaLength() {
|
||||
int j = array.length;
|
||||
@@ -258,10 +261,8 @@ public class LTable extends LValue {
|
||||
|
||||
// find `i' and `j' such that i is present and j is not
|
||||
int i = 0;
|
||||
while ( containsKey(j) && j < MAX_KEY ) {
|
||||
for ( ++j; containsKey(j) && j < MAX_KEY; j*=2 )
|
||||
i = j;
|
||||
j *= 2;
|
||||
}
|
||||
|
||||
// binary search
|
||||
while ( j - i > 1) {
|
||||
@@ -289,7 +290,7 @@ public class LTable extends LValue {
|
||||
org.luaj.vm.LTable t = (org.luaj.vm.LTable) metatable;
|
||||
LValue m = t.get(TM_MODE);
|
||||
if ( "v".equals(m.toJavaString()) ) {
|
||||
// m_backing = new WeakBacking(m_backing);
|
||||
return new LWeakTable(this);
|
||||
}
|
||||
this.m_metatable = t;
|
||||
}
|
||||
@@ -435,8 +436,8 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
private boolean compare(int i, int j, LuaState vm, LValue cmpfunc) {
|
||||
LValue a = get(i);
|
||||
LValue b = get(j);
|
||||
LValue a = get(i+1);
|
||||
LValue b = get(j+1);
|
||||
if ( a.isNil() || b.isNil() )
|
||||
return false;
|
||||
if ( ! cmpfunc.isNil() ) {
|
||||
@@ -453,9 +454,9 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
private void swap(int i, int j) {
|
||||
LValue a = get(i);
|
||||
put(i, get(j));
|
||||
put(j, a);
|
||||
LValue a = get(i+1);
|
||||
put(i+1, get(j+1));
|
||||
put(j+1, a);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,7 +479,7 @@ public class LTable extends LValue {
|
||||
Object a = array[i];
|
||||
if ( a != null ) {
|
||||
vm.pushinteger(i+1);
|
||||
vm.pushlvalue((LValue)a);
|
||||
vm.pushlvalue(normalizeGet(a));
|
||||
return true;
|
||||
} else if ( indexedonly ) {
|
||||
vm.pushnil();
|
||||
@@ -493,7 +494,7 @@ public class LTable extends LValue {
|
||||
if ( v != null ) {
|
||||
LValue k = hashKeys[i];
|
||||
vm.pushlvalue(k);
|
||||
vm.pushlvalue((LValue)v);
|
||||
vm.pushlvalue(normalizeGet(v));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -508,7 +509,7 @@ public class LTable extends LValue {
|
||||
|
||||
// first iteration
|
||||
if ( key.isNil() )
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
// is `key' inside array part?
|
||||
if ( key.isInteger() ) {
|
||||
|
||||
@@ -36,6 +36,17 @@ public class LWeakTable extends LTable {
|
||||
super(narray, nhash);
|
||||
}
|
||||
|
||||
public LWeakTable(LTable copy) {
|
||||
super( copy.array.length, copy.hashKeys.length );
|
||||
for ( int i=0, k=1, n=copy.array.length; i<n; i++, k++ )
|
||||
this.put( k, copy.get(k) );
|
||||
for ( int i=0, n=copy.hashKeys.length; i<n; i++ ) {
|
||||
LValue k = copy.hashKeys[i];
|
||||
if ( k != null )
|
||||
this.put( k, copy.get(k) );
|
||||
}
|
||||
}
|
||||
|
||||
protected LValue normalizeGet(Object val) {
|
||||
if ( val != null )
|
||||
val = ((WeakReference)val).get();
|
||||
@@ -46,4 +57,14 @@ public class LWeakTable extends LTable {
|
||||
return val==LNil.NIL? null: new WeakReference(val);
|
||||
}
|
||||
|
||||
public boolean next(LuaState vm, LValue key, boolean indexedonly) {
|
||||
while ( super.next(vm, key, indexedonly) ) {
|
||||
if ( ! vm.isnil(-1) )
|
||||
return true;
|
||||
vm.pop(1);
|
||||
key = vm.poplvalue();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
|
||||
table.insert(t,'six');
|
||||
table.insert(t,1,'seven');
|
||||
table.insert(t,4,'eight');
|
||||
table.insert(t,7,'nine');
|
||||
table.insert(t,10,'ten'); print( #t )
|
||||
|
||||
|
||||
-- concat
|
||||
print( '-- concat tests' )
|
||||
function tryconcat(t)
|
||||
@@ -30,26 +38,26 @@ function eles(t,f)
|
||||
end
|
||||
|
||||
-- insert, maxn
|
||||
print( '-- insert, maxn tests' )
|
||||
print( '-- insert, len tests' )
|
||||
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
|
||||
print( eles(t) )
|
||||
table.insert(t,'six'); print( eles(t) )
|
||||
table.insert(t,1,'seven'); print( eles(t) )
|
||||
table.insert(t,4,'eight'); print( eles(t) )
|
||||
table.insert(t,7,'nine'); print( eles(t) )
|
||||
table.insert(t,10,'ten'); print( eles(t) )
|
||||
print( eles(t), #t )
|
||||
table.insert(t,'six'); print( eles(t), #t )
|
||||
table.insert(t,1,'seven'); print( eles(t), #t )
|
||||
table.insert(t,4,'eight'); print( eles(t), #t )
|
||||
table.insert(t,7,'nine'); print( eles(t), #t )
|
||||
table.insert(t,10,'ten'); print( eles(t), #t )
|
||||
|
||||
-- remove
|
||||
print( '-- remove tests' )
|
||||
t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' }
|
||||
print( eles(t) )
|
||||
print( 'table.remove(t)', table.remove(t) ); print( eles(t) )
|
||||
print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t) )
|
||||
print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t) )
|
||||
print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t) )
|
||||
print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t) )
|
||||
print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t) )
|
||||
print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t) )
|
||||
print( eles(t), #t )
|
||||
print( 'table.remove(t)', table.remove(t) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t), #t )
|
||||
print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t), #t )
|
||||
|
||||
-- sort
|
||||
print( '-- sort tests' )
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
|
||||
|
||||
function newtable(t)
|
||||
n = setmetatable(t,{__mode="v"})
|
||||
for k,v in pairs(t) do
|
||||
n[k] = v
|
||||
end
|
||||
return n;
|
||||
end
|
||||
|
||||
-- normalized printing
|
||||
function eles(t,f)
|
||||
f = f or pairs
|
||||
all = {}
|
||||
for k,v in f(t) do
|
||||
if type(v) == 'table' then
|
||||
v = '{'..tostring(v.v)..'}'
|
||||
end
|
||||
table.insert( all, "["..tostring(k).."]="..tostring(v) )
|
||||
end
|
||||
table.sort( all )
|
||||
return tostring(t).."{"..table.concat(all,',').."}"
|
||||
return "{"..table.concat(all,',').."}"
|
||||
end
|
||||
|
||||
function newtable(t)
|
||||
return setmetatable(t,{__mode="v"})
|
||||
end
|
||||
|
||||
function new(a)
|
||||
return {v='_'..tostring(a).."_"}
|
||||
end
|
||||
|
||||
-- basic weak-reference table test
|
||||
local src = "return { 'one', 'two', 'three', 'four', a='aaa', b='bbb', c='ccc', d='ddd'}"
|
||||
local weak = newtable( loadstring(src)() )
|
||||
local weak = newtable{ new('one'), new('two'), new('three'), new('four'), a=new('aaa'), b=new('bbb'), c=new('ccc'), d=new('ddd') }
|
||||
local strong = { weak[1], weak[3], a=weak.a, c=weak.c }
|
||||
print( 'before, weak:', eles(weak) )
|
||||
print( 'before, strong:', eles(strong) )
|
||||
|
||||
Reference in New Issue
Block a user