Need advice on how to get table index of argument

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Need advice on how to get table index of argument

Lee Shallis
I'll start with an example of how the function is called:
handle:write(0xBADF00D,{0xC0,0xFF,0xEE})
Would this be the right way to extra each value in the second argument's table?
int lua_proc_change_data( lua_State *L ) {
proc_handle_t **handle = (proc_handle_t**)
luaL_checkudata(L,1,PROC_HANDLE_CLASS);
intptr_t addr = luaL_checkinteger(L,2);
intptr_t size, i;
uchar * array;
if ( !lua_istable(L,3) ) {
lua_pushinteger(L,0);
return 1;
}
size = lua_len(L,3);
if ( size < 1 ) {
lua_pushinteger(L,0);
return 1;
}
array = calloc( size, 1 );
for ( i = 0; i < size; ++i ) {
lua_pushinteger(L,i+1);
lua_gettable(L,3);
array[i] = lua_checkinteger(L,-1);
}
size = proc_change_data( NULL, *handle, addr, array, size );
free(array);
if ( size < 1 ) {
lua_pushinteger(L,0);
return 1;
}
lua_pushinteger(L,0);
return 1;
}
Reply | Threaded
Open this post in threaded view
|

Re: Need advice on how to get table index of argument

Jerome Vuarand
On Thu, 13 Feb 2020 at 18:49, Lee Shallis <[hidden email]> wrote:

> I'll start with an example of how the function is called:
> handle:write(0xBADF00D,{0xC0,0xFF,0xEE})
> Would this be the right way to extra each value in the second argument's table?
>>
>> int lua_proc_change_data( lua_State *L ) {
>> proc_handle_t **handle = (proc_handle_t**)
>> luaL_checkudata(L,1,PROC_HANDLE_CLASS);
>> intptr_t addr = luaL_checkinteger(L,2);
>> intptr_t size, i;
>> uchar * array;
>> if ( !lua_istable(L,3) ) {
>> lua_pushinteger(L,0);
>> return 1;
>> }
>> size = lua_len(L,3);
>> if ( size < 1 ) {
>> lua_pushinteger(L,0);
>> return 1;
>> }
>> array = calloc( size, 1 );
>> for ( i = 0; i < size; ++i ) {
>> lua_pushinteger(L,i+1);
>> lua_gettable(L,3);
>> array[i] = lua_checkinteger(L,-1);
>> }
>> size = proc_change_data( NULL, *handle, addr, array, size );
>> free(array);
>> if ( size < 1 ) {
>> lua_pushinteger(L,0);
>> return 1;
>> }
>> lua_pushinteger(L,0);
>> return 1;
>> }

That should work for small tables as second argument. The right way
needs a lua_pop(L,1) after lua_checkinteger(L,-1).

As a side note, you should send your emails to this mailing list in
plain text, and when you include code it would help to have it
indented. That was so hard to read I probably won't bother next time I
see your big font and your fake quote.

Reply | Threaded
Open this post in threaded view
|

Re: Need advice on how to get table index of argument

Andrew Gierth
In reply to this post by Lee Shallis
>>>>> "Lee" == Lee Shallis <[hidden email]> writes:

 Lee> I'll start with an example of how the function is called:
 Lee> handle:write(0xBADF00D,{0xC0,0xFF,0xEE})
 Lee> Would this be the right way to extra each value in the second
 Lee> argument's table?

 >> if ( !lua_istable(L,3) ) {

In cases like this you have to ask: does the object actually _have_ to
be a table, or could it be anything that's indexable with integers?

If the latter, then lua_istable is too strict a check.

 >> array = calloc( size, 1 );

This will leak the allocated array permanently if any of the
checkinteger calls throws an error. You can use a temporary userdata
which will be GC'd, or some other variation.

 >> for ( i = 0; i < size; ++i ) {
 >> lua_pushinteger(L,i+1);
 >> lua_gettable(L,3);

See lua_geti() to combine these two calls

 >> array[i] = lua_checkinteger(L,-1);

You need to pop the value off the stack after using it.

And I second the other comments about providing code as plain text with
proper indentation, not mangled into html.

--
Andrew.

Reply | Threaded
Open this post in threaded view
|

Re: Need advice on how to get table index of argument

Tim Hill
In reply to this post by Lee Shallis


On Feb 13, 2020, at 10:48 AM, Lee Shallis <[hidden email]> wrote:

I'll start with an example of how the function is called:
handle:write(0xBADF00D,{0xC0,0xFF,0xEE})
Would this be the right way to extra each value in the second argument's table?
int lua_proc_change_data( lua_State *L ) {
proc_handle_t **handle = (proc_handle_t**)
luaL_checkudata(L,1,PROC_HANDLE_CLASS);
intptr_t addr = luaL_checkinteger(L,2);
intptr_t size, i;
uchar * array;
if ( !lua_istable(L,3) ) {
lua_pushinteger(L,0);
return 1;
}
size = lua_len(L,3);
if ( size < 1 ) {
lua_pushinteger(L,0);
return 1;
}
array = calloc( size, 1 );
for ( i = 0; i < size; ++i ) {
lua_pushinteger(L,i+1);
lua_gettable(L,3);
array[i] = lua_checkinteger(L,-1);
}
size = proc_change_data( NULL, *handle, addr, array, size );
free(array);
if ( size < 1 ) {
lua_pushinteger(L,0);
return 1;
}
lua_pushinteger(L,0);
return 1;
}

Couple of things…

— In the main “for” loop you are adding a stack item for each loop iteration… this will overflow the stack if “size” is big enough. You need to pop the integer off the stack after assign it to array[I].

— Although its unlikely to happen in the real-world, you should ALWAYS check that calloc() does not return NULL. If it does, your function will crash the app with a pointer exception.

— I dont know how critical performance is here, but allocating a C array dynamically for small blocks is pretty wasteful. If it were me I would have a small array available on the stack, and use that if “size” were small (say, 16 or less), only doing the alloc/free if size were above this threshold.

— You might want to look at the function lua_geti(), which is a cleaner way to get a table item using an C integer index (easier to use than lua_gettable().


—Tim