Fix table library type checking.
This commit is contained in:
@@ -97,12 +97,16 @@ public class TableLib extends LFunction {
|
||||
case CONCAT: {
|
||||
int n = vm.gettop();
|
||||
LTable table = vm.checktable(2);
|
||||
LString sep = (n>=3? vm.checklstring(3): null);
|
||||
int i = (n>=4? vm.checkint(4): 1);
|
||||
int j = (n>=5? vm.checkint(5): table.luaLength());
|
||||
LString sep = vm.optlstring(3,null);
|
||||
int i = vm.optint(4,1);
|
||||
int j = vm.optint(5,-1);
|
||||
if ( j == -1 )
|
||||
j = table.luaLength();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
for ( int k=i; k<=j; k++ ) {
|
||||
LValue v = table.get(k);
|
||||
if ( ! v.isString() )
|
||||
vm.argerror(2, "table contains non-strings");
|
||||
v.luaConcatTo(baos);
|
||||
if ( k<j && sep!=null )
|
||||
sep.luaConcatTo( baos );
|
||||
@@ -144,12 +148,19 @@ public class TableLib extends LFunction {
|
||||
* The default value for pos is n+1, where n is the length of the table (see §2.5.5), so that a call
|
||||
* table.insert(t,x) inserts x at the end of table t.
|
||||
*/
|
||||
case INSERT: {
|
||||
int n = vm.gettop();
|
||||
case INSERT: {
|
||||
LTable table = vm.checktable(2);
|
||||
int pos = (n>=4? vm.checkint(3): 0);
|
||||
LValue value = vm.topointer(-1);
|
||||
table.luaInsertPos( pos, value );
|
||||
int pos = 0;
|
||||
switch ( vm.gettop() ) {
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
pos = vm.checkint(3);
|
||||
break;
|
||||
default:
|
||||
vm.error( "wrong number of arguments to 'insert'" );
|
||||
}
|
||||
table.luaInsertPos( pos, vm.topointer(-1) );
|
||||
vm.resettop();
|
||||
break;
|
||||
}
|
||||
@@ -175,7 +186,7 @@ public class TableLib extends LFunction {
|
||||
case REMOVE: {
|
||||
int n = vm.gettop();
|
||||
LTable table = vm.checktable(2);
|
||||
int pos = (n>=3? vm.checkint(3): 0);
|
||||
int pos = vm.optint(3,0);
|
||||
vm.resettop();
|
||||
LValue removed = table.luaRemovePos( pos );
|
||||
if ( removed != LNil.NIL )
|
||||
@@ -194,7 +205,7 @@ public class TableLib extends LFunction {
|
||||
*/
|
||||
case SORT: {
|
||||
LTable table = vm.checktable(2);
|
||||
LValue compare = vm.checkfunction(3);
|
||||
LValue compare = (vm.isnoneornil(3)? LNil.NIL: vm.checkfunction(3));
|
||||
table.luaSort( vm, compare );
|
||||
vm.resettop();
|
||||
break;
|
||||
|
||||
@@ -309,7 +309,8 @@ public class LValue {
|
||||
|
||||
/** Concatenate this value to a ByteArrayOutputStream */
|
||||
public void luaConcatTo(ByteArrayOutputStream baos) {
|
||||
throw new LuaErrorException( "attempt to concat ? (a "+luaGetTypeName()+" value)");
|
||||
byte[] b = toJavaString().getBytes();
|
||||
baos.write(b,0,b.length);
|
||||
}
|
||||
|
||||
/** Return true if this is a LString */
|
||||
|
||||
@@ -2685,7 +2685,7 @@ public class LuaState extends Lua {
|
||||
*/
|
||||
public int checkint(int narg) {
|
||||
LValue v = tolnumber(narg);
|
||||
if ( ! v.isInteger() )
|
||||
if ( v.isNil() )
|
||||
typerror(narg, Lua.LUA_TNUMBER);
|
||||
return v.toJavaInt();
|
||||
}
|
||||
@@ -2722,7 +2722,10 @@ public class LuaState extends Lua {
|
||||
* @return LNumber value if the argument is a number or can be converted to one
|
||||
*/
|
||||
public LNumber checknumber(int narg) {
|
||||
return (LNumber) checktype(narg, Lua.LUA_TTABLE);
|
||||
LValue v = topointer(narg).luaToNumber();
|
||||
if ( v.isNil() )
|
||||
typerror(narg, Lua.LUA_TNUMBER);
|
||||
return (LNumber) v;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2799,11 +2802,101 @@ public class LuaState extends Lua {
|
||||
typerror(ud, expected.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function argument <code>narg</code> is a number, returns this
|
||||
* number cast to an <code>int</code>. If this argument is absent or is
|
||||
* <b>nil</b>, returns <code>d</code>. Otherwise, raises an error.
|
||||
* @param narg the argument number
|
||||
* @param d the default value when the argument is nil or not supplied
|
||||
* @throws LuaErrorException if the value cannot be converted to an int
|
||||
* @return int value if the argument is an int, or d
|
||||
*/
|
||||
public int optint(int narg, int d) {
|
||||
LNumber n = optnumber(narg,null);
|
||||
return (n==null? d: n.toJavaInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function argument <code>narg</code> is a number, returns this
|
||||
* number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
|
||||
* If this argument is absent or is <b>nil</b>, returns <code>d</code>.
|
||||
* Otherwise, raises an error.
|
||||
* @param narg the argument number
|
||||
* @param d the default value when the argument is nil or not supplied
|
||||
* @throws LuaErrorException if the value cannot be converted to an int
|
||||
* @return int value if the argument is an int, or d
|
||||
*/
|
||||
public LInteger optinteger(int narg, int d) {
|
||||
return LInteger.valueOf(optint(narg,d));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function argument <code>narg</code> is a number, returns this
|
||||
* number cast to a <code>long</code>. If this argument is absent or is
|
||||
* <b>nil</b>, returns <code>d</code>. Otherwise, raises an error.
|
||||
* @param narg the argument number
|
||||
* @param d the default value when the argument is nil or not supplied
|
||||
* @throws LuaErrorException if the value cannot be converted to an number
|
||||
* @return int value if the argument is an number, or d
|
||||
*/
|
||||
public long optlong(int narg, long d) {
|
||||
LNumber n = optnumber(narg,null);
|
||||
return (n==null? d: n.toJavaLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to indicate a vm internal error has occurred.
|
||||
* Generally, this is not recoverable, so we convert to
|
||||
* a lua error during production so that the code may recover.
|
||||
* If the function argument <code>narg</code> is a number, returns this
|
||||
* number. If this argument is absent or is <b>nil</b>, returns
|
||||
* <code>d</code>. Otherwise, raises an error.
|
||||
* @param narg the argument number
|
||||
* @param d the default value when the argument is nil or not supplied
|
||||
* @throws LuaErrorException if the value cannot be converted to an number
|
||||
* @return int value if the argument is an number, or d
|
||||
*/
|
||||
public LNumber optnumber(int narg, LNumber d) {
|
||||
LValue v = topointer(narg);
|
||||
if ( v.isNil() )
|
||||
return d;
|
||||
v = v.luaToNumber();
|
||||
if ( v.isNil() )
|
||||
typerror(narg, Lua.LUA_TNUMBER);
|
||||
return (LNumber) v;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function argument <code>narg</code> is a string, returns this
|
||||
* string. If this argument is absent or is <b>nil</b>, returns
|
||||
* <code>d</code>. Otherwise, raises an error.
|
||||
*/
|
||||
public LString optlstring(int narg, LString d) {
|
||||
LValue v = topointer(narg);
|
||||
if ( v.isNil() )
|
||||
return d;
|
||||
if ( ! v.isString() )
|
||||
typerror(narg, Lua.LUA_TSTRING);
|
||||
return v.luaAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function argument <code>narg</code> is a string, returns this
|
||||
* string. If this argument is absent or is <b>nil</b>, returns
|
||||
* <code>d</code>. Otherwise, raises an error.
|
||||
*/
|
||||
public String optstring(int narg, String d) {
|
||||
LValue v = topointer(narg);
|
||||
if ( v.isNil() )
|
||||
return d;
|
||||
if ( ! v.isString() )
|
||||
typerror(narg, Lua.LUA_TSTRING);
|
||||
return v.toJavaString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to indicate a vm internal error has occurred. Generally, this is
|
||||
* not recoverable, so we convert to a lua error during production so that
|
||||
* the code may recover.
|
||||
*/
|
||||
public static void vmerror(String description) {
|
||||
throw new LuaErrorException( "internal error: "+description );
|
||||
|
||||
@@ -196,6 +196,9 @@ print( 'pcall(tonumber,false)', pcall(tonumber,false) )
|
||||
print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) )
|
||||
print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) )
|
||||
print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) )
|
||||
print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") )
|
||||
print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") )
|
||||
print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") )
|
||||
|
||||
-- tostring
|
||||
print( 'pcall(tostring)', pcall(tostring) )
|
||||
|
||||
Reference in New Issue
Block a user