Fix table library type checking.

This commit is contained in:
James Roseborough
2008-07-17 22:44:28 +00:00
parent 06908c3b60
commit 1885f9b618
4 changed files with 124 additions and 16 deletions

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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 );

View File

@@ -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) )