Refactor table implementation.
This commit is contained in:
@@ -126,6 +126,10 @@ public class LuaInteger extends LuaNumber {
|
||||
return v;
|
||||
}
|
||||
|
||||
public static int hashCode(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// unary operators
|
||||
public LuaValue neg() { return valueOf(-(long)v); }
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ public class LuaUserdata extends LuaValue {
|
||||
m_instance = obj;
|
||||
m_metatable = metatable;
|
||||
}
|
||||
|
||||
|
||||
public String tojstring() {
|
||||
return String.valueOf(m_instance);
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public class LuaUserdata extends LuaValue {
|
||||
}
|
||||
|
||||
// __eq metatag processing
|
||||
public boolean eqmt( LuaValue val ) {
|
||||
public boolean eqmt( LuaValue val ) {
|
||||
return m_metatable!=null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()): false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,7 +1384,7 @@ public class LuaValue extends Varargs {
|
||||
* @see LuaFunction#s_metatable
|
||||
* @see LuaThread#s_metatable
|
||||
*/
|
||||
public LuaValue getmetatable() { return null; };
|
||||
public LuaValue getmetatable() { return null; }
|
||||
|
||||
/**
|
||||
* Set the metatable for this {@link LuaValue}
|
||||
@@ -3131,24 +3131,12 @@ public class LuaValue extends Varargs {
|
||||
*/
|
||||
public LuaString strvalue() { typerror("strValue"); return null; }
|
||||
|
||||
/** Return the key part of this value if it is a weak table entry, or {@link NIL} if it was weak and is no longer referenced.
|
||||
* @return {@link LuaValue} key, or {@link NIL} if it was weak and is no longer referenced.
|
||||
* @see WeakTable
|
||||
*/
|
||||
public LuaValue strongkey() { return strongvalue(); }
|
||||
|
||||
/** Return this value as a strong reference, or {@link NIL} if it was weak and is no longer referenced.
|
||||
* @return {@link LuaValue} referred to, or {@link NIL} if it was weak and is no longer referenced.
|
||||
/** Return this value as a strong reference, or null if it was weak and is no longer referenced.
|
||||
* @return {@link LuaValue} referred to, or null if it was weak and is no longer referenced.
|
||||
* @see WeakTable
|
||||
*/
|
||||
public LuaValue strongvalue() { return this; }
|
||||
|
||||
/** Test if this is a weak reference and its value no longer is referenced.
|
||||
* @return true if this is a weak reference whose value no longer is referenced
|
||||
* @see WeakTable
|
||||
*/
|
||||
public boolean isweaknil() { return false; }
|
||||
|
||||
/** Convert java boolean to a {@link LuaValue}.
|
||||
*
|
||||
* @param b boolean value to convert
|
||||
@@ -3215,7 +3203,7 @@ public class LuaValue extends Varargs {
|
||||
* @return new {@link LuaTable} instance with no values and no metatable, but preallocated for array and hashed elements.
|
||||
*/
|
||||
public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); }
|
||||
|
||||
|
||||
/** Construct a {@link LuaTable} initialized with supplied array values.
|
||||
* @param unnamedValues array of {@link LuaValue} containing the values to use in initialization
|
||||
* @return new {@link LuaTable} instance with sequential elements coming from the array.
|
||||
@@ -3229,7 +3217,7 @@ public class LuaValue extends Varargs {
|
||||
* @return new {@link LuaTable} instance with sequential elements coming from the array and varargs.
|
||||
*/
|
||||
public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }
|
||||
|
||||
|
||||
/** Construct a {@link LuaTable} initialized with supplied named values.
|
||||
* @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization
|
||||
* in order {@code {key-a, value-a, key-b, value-b, ...} }
|
||||
@@ -3365,6 +3353,26 @@ public class LuaValue extends Varargs {
|
||||
return h;
|
||||
}
|
||||
|
||||
/** Construct a Metatable instance from the given LuaValue */
|
||||
protected static Metatable metatableOf(LuaValue mt) {
|
||||
if ( mt != null && mt.istable() ) {
|
||||
LuaValue mode = mt.rawget(MODE);
|
||||
if ( mode.isstring() ) {
|
||||
String m = mode.tojstring();
|
||||
boolean weakkeys = m.indexOf('k') >= 0;
|
||||
boolean weakvalues = m.indexOf('v') >= 0;
|
||||
if ( weakkeys || weakvalues ) {
|
||||
return new WeakTable(weakkeys, weakvalues, mt);
|
||||
}
|
||||
}
|
||||
return (LuaTable)mt;
|
||||
} else if ( mt != null ) {
|
||||
return new NonTableMetatable( mt );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Throw {@link LuaError} indicating index was attempted on illegal type
|
||||
* @throws LuaError when called.
|
||||
*/
|
||||
|
||||
51
src/core/org/luaj/vm2/Metatable.java
Normal file
51
src/core/org/luaj/vm2/Metatable.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Luaj.org. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
package org.luaj.vm2;
|
||||
|
||||
import org.luaj.vm2.LuaTable.Slot;
|
||||
|
||||
/**
|
||||
* Provides operations that depend on the __mode key of the metatable.
|
||||
*/
|
||||
interface Metatable {
|
||||
|
||||
/** Return whether or not this table's keys are weak. */
|
||||
public boolean useWeakKeys();
|
||||
|
||||
/** Return whether or not this table's values are weak. */
|
||||
public boolean useWeakValues();
|
||||
|
||||
/** Return this metatable as a LuaValue. */
|
||||
public LuaValue toLuaValue();
|
||||
|
||||
/** Return an instance of Slot appropriate for the given key and value. */
|
||||
public Slot entry( LuaValue key, LuaValue value );
|
||||
|
||||
/** Returns the given value wrapped in a weak reference if appropriate. */
|
||||
public LuaValue wrap( LuaValue value );
|
||||
|
||||
/**
|
||||
* Returns the value at the given index in the array, or null if it is a weak reference that
|
||||
* has been dropped.
|
||||
*/
|
||||
public LuaValue arrayget(LuaValue[] array, int index);
|
||||
}
|
||||
36
src/core/org/luaj/vm2/NonTableMetatable.java
Normal file
36
src/core/org/luaj/vm2/NonTableMetatable.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package org.luaj.vm2;
|
||||
|
||||
import org.luaj.vm2.LuaTable.Slot;
|
||||
|
||||
class NonTableMetatable implements Metatable {
|
||||
|
||||
private final LuaValue value;
|
||||
|
||||
public NonTableMetatable(LuaValue value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean useWeakKeys() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean useWeakValues() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public LuaValue toLuaValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Slot entry(LuaValue key, LuaValue value) {
|
||||
return LuaTable.defaultEntry(key, value);
|
||||
}
|
||||
|
||||
public LuaValue wrap(LuaValue value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
public LuaValue arrayget(LuaValue[] array, int index) {
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
|
||||
* Copyright (c) 2009-2011, 2013 Luaj.org. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -23,7 +23,8 @@ package org.luaj.vm2;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.luaj.vm2.lib.TwoArgFunction;
|
||||
import org.luaj.vm2.LuaTable.Slot;
|
||||
import org.luaj.vm2.LuaTable.StrongSlot;
|
||||
|
||||
/**
|
||||
* Subclass of {@link LuaTable} that provides weak key and weak value semantics.
|
||||
@@ -34,79 +35,276 @@ import org.luaj.vm2.lib.TwoArgFunction;
|
||||
* However, calling the constructors directly when weak tables are required from
|
||||
* Java will reduce overhead.
|
||||
*/
|
||||
public class WeakTable extends LuaTable {
|
||||
private boolean weakkeys,weakvalues;
|
||||
|
||||
/**
|
||||
public class WeakTable implements Metatable {
|
||||
|
||||
private boolean weakkeys, weakvalues;
|
||||
private LuaValue backing;
|
||||
|
||||
public static LuaTable make(boolean weakkeys, boolean weakvalues) {
|
||||
LuaString mode;
|
||||
if ( weakkeys && weakvalues ) {
|
||||
mode = LuaString.valueOf("kv");
|
||||
} else if ( weakkeys ) {
|
||||
mode = LuaString.valueOf("k");
|
||||
} else if ( weakvalues ) {
|
||||
mode = LuaString.valueOf("v");
|
||||
} else {
|
||||
return LuaTable.tableOf();
|
||||
}
|
||||
LuaTable table = LuaTable.tableOf();
|
||||
LuaTable mt = LuaTable.tableOf(new LuaValue[] { LuaValue.MODE, mode });
|
||||
table.setmetatable(mt);
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a table with weak keys, weak values, or both
|
||||
* @param weakkeys true to let the table have weak keys
|
||||
* @param weakvalues true to let the table have weak values
|
||||
*/
|
||||
public WeakTable(boolean weakkeys, boolean weakvalues) {
|
||||
this(weakkeys, weakvalues, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a table with weak keys, weak values, or both, and an initial capacity
|
||||
* @param weakkeys true to let the table have weak keys
|
||||
* @param weakvalues true to let the table have weak values
|
||||
* @param narray capacity of array part
|
||||
* @param nhash capacity of hash part
|
||||
*/
|
||||
protected WeakTable(boolean weakkeys, boolean weakvalues, int narray, int nhash) {
|
||||
super(narray, nhash);
|
||||
public WeakTable(boolean weakkeys, boolean weakvalues, LuaValue backing) {
|
||||
this.weakkeys = weakkeys;
|
||||
this.weakvalues = weakvalues;
|
||||
this.backing = backing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a table with weak keys, weak values, or both, and a source of initial data
|
||||
* @param weakkeys true to let the table have weak keys
|
||||
* @param weakvalues true to let the table have weak values
|
||||
* @param source {@link LuaTable} containing the initial elements
|
||||
*/
|
||||
protected WeakTable(boolean weakkeys, boolean weakvalues, LuaTable source) {
|
||||
this(weakkeys, weakvalues, source.getArrayLength(), source.getHashLength());
|
||||
Varargs n;
|
||||
LuaValue k = NIL;
|
||||
while ( !(k = ((n = source.next(k)).arg1())).isnil() )
|
||||
rawset(k, n.arg(2));
|
||||
m_metatable = source.m_metatable;
|
||||
}
|
||||
|
||||
public void presize( int narray ) {
|
||||
super.presize(narray);
|
||||
public boolean useWeakKeys() {
|
||||
return weakkeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Presize capacity of both array and hash parts.
|
||||
* @param narray capacity of array part
|
||||
* @param nhash capacity of hash part
|
||||
*/
|
||||
public void presize(int narray, int nhash) {
|
||||
super.presize(narray, nhash);
|
||||
}
|
||||
|
||||
protected int getArrayLength() {
|
||||
return super.getArrayLength();
|
||||
public boolean useWeakValues() {
|
||||
return weakvalues;
|
||||
}
|
||||
|
||||
protected int getHashLength() {
|
||||
return super.getHashLength();
|
||||
public LuaValue toLuaValue() {
|
||||
return backing;
|
||||
}
|
||||
|
||||
protected LuaTable changemode(boolean weakkeys, boolean weakvalues) {
|
||||
this.weakkeys = weakkeys;
|
||||
this.weakvalues = weakvalues;
|
||||
return this;
|
||||
|
||||
public Slot entry(LuaValue key, LuaValue value) {
|
||||
value = value.strongvalue();
|
||||
if ( value == null )
|
||||
return null;
|
||||
if ( weakkeys && !( key.isnumber() || key.isstring() || key.isboolean() )) {
|
||||
if ( weakvalues && !( value.isnumber() || value.isstring() || value.isboolean() )) {
|
||||
return new WeakKeyAndValueSlot( key, value, null );
|
||||
} else {
|
||||
return new WeakKeySlot( key, value, null );
|
||||
}
|
||||
}
|
||||
if ( weakvalues && ! (value.isnumber() || value.isstring() || value.isboolean() )) {
|
||||
return new WeakValueSlot( key, value, null );
|
||||
}
|
||||
return LuaTable.defaultEntry( key, value );
|
||||
}
|
||||
|
||||
|
||||
public static abstract class WeakSlot implements Slot {
|
||||
|
||||
protected Object key;
|
||||
protected Object value;
|
||||
protected Slot next;
|
||||
|
||||
protected WeakSlot(Object key, Object value, Slot next) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public abstract int keyindex( int hashMask );
|
||||
|
||||
public abstract Slot set(LuaValue value);
|
||||
|
||||
public StrongSlot first() {
|
||||
LuaValue key = strongkey();
|
||||
LuaValue value = strongvalue();
|
||||
if ( key != null && value != null ) {
|
||||
return new LuaTable.NormalEntry(key, value);
|
||||
} else {
|
||||
this.key = null;
|
||||
this.value = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public StrongSlot find(LuaValue key) {
|
||||
StrongSlot first = first();
|
||||
return ( first != null ) ? first.find( key ) : null;
|
||||
}
|
||||
|
||||
public boolean keyeq(LuaValue key) {
|
||||
StrongSlot first = first();
|
||||
return ( first != null ) && first.keyeq( key );
|
||||
}
|
||||
|
||||
public Slot rest() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public int arraykey(int max) {
|
||||
// Integer keys can never be weak.
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Slot set(StrongSlot target, LuaValue value) {
|
||||
LuaValue key = strongkey();
|
||||
if ( key != null && target.find( key ) != null ) {
|
||||
return set( value );
|
||||
} else if ( key != null ) {
|
||||
// Our key is still good.
|
||||
next = next.set( target, value );
|
||||
return this;
|
||||
} else {
|
||||
// our key was dropped, remove ourselves from the chain.
|
||||
return next.set( target, value );
|
||||
}
|
||||
}
|
||||
|
||||
public Slot add( Slot entry ) {
|
||||
next = ( next != null ) ? next.add( entry ) : entry;
|
||||
if ( strongkey() != null && strongvalue() != null ) {
|
||||
return this;
|
||||
} else {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
public Slot remove( StrongSlot target ) {
|
||||
LuaValue key = strongkey();
|
||||
if ( key == null ) {
|
||||
return next.remove( target );
|
||||
} else if ( target.keyeq( key ) ) {
|
||||
this.value = null;
|
||||
return this;
|
||||
} else {
|
||||
next = next.remove( target );
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Slot relink( Slot rest ) {
|
||||
if ( strongkey() != null && strongvalue() != null ) {
|
||||
if ( rest == null && this.next == null ) {
|
||||
return this;
|
||||
} else {
|
||||
return copy( rest );
|
||||
}
|
||||
} else {
|
||||
return rest;
|
||||
}
|
||||
}
|
||||
|
||||
public LuaValue strongkey() {
|
||||
return (LuaValue) key;
|
||||
}
|
||||
|
||||
public LuaValue strongvalue() {
|
||||
return (LuaValue) value;
|
||||
}
|
||||
|
||||
protected abstract WeakSlot copy( Slot next );
|
||||
}
|
||||
|
||||
static class WeakKeySlot extends WeakSlot {
|
||||
|
||||
private final int keyhash;
|
||||
|
||||
protected WeakKeySlot( LuaValue key, LuaValue value, Slot next ) {
|
||||
super(weaken(key), value, next);
|
||||
keyhash = key.hashCode();
|
||||
}
|
||||
|
||||
protected WeakKeySlot( WeakKeySlot copyFrom, Slot next ) {
|
||||
super( copyFrom.key, copyFrom.value, next );
|
||||
this.keyhash = copyFrom.keyhash;
|
||||
}
|
||||
|
||||
public int keyindex( int mask ) {
|
||||
return LuaTable.hashmod( keyhash, mask );
|
||||
}
|
||||
|
||||
public Slot set(LuaValue value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LuaValue strongkey() {
|
||||
return strengthen( key );
|
||||
}
|
||||
|
||||
protected WeakSlot copy( Slot rest ) {
|
||||
return new WeakKeySlot( this, rest );
|
||||
}
|
||||
}
|
||||
|
||||
static class WeakValueSlot extends WeakSlot {
|
||||
|
||||
protected WeakValueSlot( LuaValue key, LuaValue value, Slot next ) {
|
||||
super( key, weaken(value), next);
|
||||
}
|
||||
|
||||
protected WeakValueSlot( WeakValueSlot copyFrom, Slot next ) {
|
||||
super( copyFrom.key, copyFrom.value, next );
|
||||
}
|
||||
|
||||
public int keyindex( int mask ) {
|
||||
return LuaTable.hashSlot( strongkey(), mask );
|
||||
}
|
||||
|
||||
public Slot set(LuaValue value) {
|
||||
this.value = weaken(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LuaValue strongvalue() {
|
||||
return strengthen( value );
|
||||
}
|
||||
|
||||
protected WeakSlot copy(Slot next) {
|
||||
return new WeakValueSlot( this, next );
|
||||
}
|
||||
}
|
||||
|
||||
static class WeakKeyAndValueSlot extends WeakSlot {
|
||||
|
||||
private final int keyhash;
|
||||
|
||||
protected WeakKeyAndValueSlot( LuaValue key, LuaValue value, Slot next ) {
|
||||
super( weaken(key), weaken(value), next );
|
||||
keyhash = key.hashCode();
|
||||
}
|
||||
|
||||
protected WeakKeyAndValueSlot(WeakKeyAndValueSlot copyFrom, Slot next) {
|
||||
super( copyFrom.key, copyFrom.value, next );
|
||||
keyhash = copyFrom.keyhash;
|
||||
}
|
||||
|
||||
public int keyindex( int hashMask ) {
|
||||
return LuaTable.hashmod( keyhash, hashMask );
|
||||
}
|
||||
|
||||
public Slot set(LuaValue value) {
|
||||
this.value = weaken(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LuaValue strongkey() {
|
||||
return strengthen( key );
|
||||
}
|
||||
|
||||
public LuaValue strongvalue() {
|
||||
return strengthen( value );
|
||||
}
|
||||
|
||||
protected WeakSlot copy( Slot next ) {
|
||||
return new WeakKeyAndValueSlot( this, next );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Self-sent message to convert a value to its weak counterpart
|
||||
* @param value value to convert
|
||||
* @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value}
|
||||
*/
|
||||
LuaValue weaken( LuaValue value ) {
|
||||
protected static LuaValue weaken( LuaValue value ) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TFUNCTION:
|
||||
case LuaValue.TTHREAD:
|
||||
@@ -118,108 +316,28 @@ public class WeakTable extends LuaTable {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public void rawset( int key, LuaValue value ) {
|
||||
if ( weakvalues )
|
||||
value = weaken( value );
|
||||
super.rawset(key, value);
|
||||
}
|
||||
|
||||
public void rawset( LuaValue key, LuaValue value ) {
|
||||
if ( weakvalues )
|
||||
value = weaken( value );
|
||||
if ( weakkeys ) {
|
||||
switch ( key.type() ) {
|
||||
case LuaValue.TFUNCTION:
|
||||
case LuaValue.TTHREAD:
|
||||
case LuaValue.TTABLE:
|
||||
case LuaValue.TUSERDATA:
|
||||
key = value = new WeakEntry(this, key, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.rawset(key, value);
|
||||
}
|
||||
|
||||
|
||||
public LuaValue rawget( int key ) {
|
||||
return super.rawget(key).strongvalue();
|
||||
}
|
||||
|
||||
public LuaValue rawget( LuaValue key ) {
|
||||
return super.rawget(key).strongvalue();
|
||||
}
|
||||
|
||||
/** Get the hash value for a key
|
||||
* key the key to look up
|
||||
* */
|
||||
protected LuaValue hashget(LuaValue key) {
|
||||
if ( hashEntries > 0 ) {
|
||||
int i = hashFindSlot(key);
|
||||
if ( hashEntries == 0 )
|
||||
return NIL;
|
||||
LuaValue v = hashValues[i];
|
||||
return v!=null? v: NIL;
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
// override to remove values for weak keys as we search
|
||||
public int hashFindSlot(LuaValue key) {
|
||||
int i = ( key.hashCode() & 0x7FFFFFFF ) % hashKeys.length;
|
||||
LuaValue k;
|
||||
while ( ( k = hashKeys[i] ) != null ) {
|
||||
if ( k.isweaknil() ) {
|
||||
hashClearSlot(i);
|
||||
if ( hashEntries == 0 )
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if ( k.raweq(key.strongkey()) )
|
||||
return i;
|
||||
i = ( i + 1 ) % hashKeys.length;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next element after a particular key in the table
|
||||
* @return key,value or nil
|
||||
* Unwrap a LuaValue from a WeakReference and/or WeakUserdata.
|
||||
* @param ref reference to convert
|
||||
* @return LuaValue or null
|
||||
* @see #weaken(LuaValue)
|
||||
*/
|
||||
public Varargs next( LuaValue key ) {
|
||||
while ( true ) {
|
||||
Varargs n = super.next(key);
|
||||
LuaValue k = n.arg1();
|
||||
if ( k.isnil() )
|
||||
return NIL;
|
||||
LuaValue ks = k.strongkey();
|
||||
LuaValue vs = n.arg(2).strongvalue();
|
||||
if ( ks.isnil() || vs.isnil() ) {
|
||||
super.rawset(k, NIL);
|
||||
} else {
|
||||
return varargsOf(ks,vs);
|
||||
}
|
||||
protected static LuaValue strengthen(Object ref) {
|
||||
if ( ref instanceof WeakReference ) {
|
||||
ref = ((WeakReference) ref).get();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------- sort support -----------------------------
|
||||
public void sort(final LuaValue comparator) {
|
||||
super.sort( new TwoArgFunction() {
|
||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||
return comparator.call( arg1.strongvalue(), arg2.strongvalue() );
|
||||
}
|
||||
} );
|
||||
if ( ref instanceof WeakValue ) {
|
||||
return ((WeakValue) ref).strongvalue();
|
||||
}
|
||||
return (LuaValue) ref;
|
||||
}
|
||||
|
||||
/** Internal class to implement weak values.
|
||||
* @see WeakTable
|
||||
*/
|
||||
static class WeakValue extends LuaValue {
|
||||
final WeakReference ref;
|
||||
WeakReference ref;
|
||||
|
||||
protected WeakValue(LuaValue value) {
|
||||
ref = new WeakReference(value);
|
||||
@@ -234,26 +352,22 @@ public class WeakTable extends LuaTable {
|
||||
illegal("typename","weak value");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return "weak<"+ref.get()+">";
|
||||
}
|
||||
|
||||
|
||||
public LuaValue strongvalue() {
|
||||
Object o = ref.get();
|
||||
return o!=null? (LuaValue)o: NIL;
|
||||
return (LuaValue)o;
|
||||
}
|
||||
|
||||
|
||||
public boolean raweq(LuaValue rhs) {
|
||||
Object o = ref.get();
|
||||
return o!=null && rhs.raweq((LuaValue)o);
|
||||
}
|
||||
|
||||
public boolean isweaknil() {
|
||||
return ref.get() == null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Internal class to implement weak userdata values.
|
||||
* @see WeakTable
|
||||
*/
|
||||
@@ -266,79 +380,34 @@ public class WeakTable extends LuaTable {
|
||||
ob = new WeakReference(value.touserdata());
|
||||
mt = value.getmetatable();
|
||||
}
|
||||
|
||||
|
||||
public LuaValue strongvalue() {
|
||||
Object u = ref.get();
|
||||
if ( u != null )
|
||||
return (LuaValue) u;
|
||||
Object o = ob.get();
|
||||
return o!=null? userdataOf(o,mt): NIL;
|
||||
}
|
||||
|
||||
public boolean raweq(LuaValue rhs) {
|
||||
if ( ! rhs.isuserdata() )
|
||||
return false;
|
||||
LuaValue v = (LuaValue) ref.get();
|
||||
if ( v != null && v.raweq(rhs) )
|
||||
return true;
|
||||
return rhs.touserdata() == ob.get();
|
||||
}
|
||||
|
||||
public boolean isweaknil() {
|
||||
return ob.get() == null || ref.get() == null;
|
||||
if ( o != null ) {
|
||||
LuaValue ud = LuaValue.userdataOf(o,mt);
|
||||
ref = new WeakReference(ud);
|
||||
return ud;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Internal class to implement weak table entries.
|
||||
* @see WeakTable
|
||||
*/
|
||||
static final class WeakEntry extends LuaValue {
|
||||
final LuaValue weakkey;
|
||||
LuaValue weakvalue;
|
||||
final int keyhash;
|
||||
public LuaValue wrap(LuaValue value) {
|
||||
return weakvalues ? weaken( value ) : value;
|
||||
}
|
||||
|
||||
private WeakEntry(WeakTable table, LuaValue key, LuaValue weakvalue) {
|
||||
this.weakkey = table.weaken(key);
|
||||
this.keyhash = key.hashCode();
|
||||
this.weakvalue = weakvalue;
|
||||
}
|
||||
|
||||
public LuaValue strongkey() {
|
||||
return weakkey.strongvalue();
|
||||
}
|
||||
|
||||
// when looking up the value, look in the keys metatable
|
||||
public LuaValue strongvalue() {
|
||||
LuaValue key = weakkey.strongvalue();
|
||||
if ( key.isnil() )
|
||||
return weakvalue = NIL;
|
||||
return weakvalue.strongvalue();
|
||||
}
|
||||
|
||||
public int type() {
|
||||
return TNONE;
|
||||
}
|
||||
|
||||
public String typename() {
|
||||
illegal("typename","weak entry");
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "weak<"+weakkey.strongvalue()+","+strongvalue()+">";
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return keyhash;
|
||||
}
|
||||
|
||||
public boolean raweq(LuaValue rhs) {
|
||||
//return rhs.raweq(weakkey.strongvalue());
|
||||
return weakkey.raweq(rhs);
|
||||
}
|
||||
|
||||
public boolean isweaknil() {
|
||||
return weakkey.isweaknil() || weakvalue.isweaknil();
|
||||
public LuaValue arrayget(LuaValue[] array, int index) {
|
||||
LuaValue value = array[index];
|
||||
if (value != null) {
|
||||
value = strengthen(value);
|
||||
if (value == null) {
|
||||
array[index] = null;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user