lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


That did it!

Many thanks everyone :)

-Raymond



On 1/19/07, Rici Lake <lua@ricilake.net> wrote:

On 19-Jan-07, at 9:44 PM, Raymond Jacobs wrote:

> Thanks for adding that Chris,
>
> We're a bit closer, I get through one element in the sub-table
>
> however when it goes through and pops off an element and goes to
> lua_next,
>
> it crashes =/

Have you:
-- made sure that you're running inside of a protected call?
-- enabled Lua's API check feature?

You're making the assumption that all keys are strings; that's
certainly not the case. If a key is a number, then the lua_tostring(l,
-2) will turn it into a string representation of that number, and
lua_next will throw an error since it won't find the resulting string
as a key in the table; if you're not running inside of a protected call
(which you always should be), then Lua will terminate the application
"with extreme prejudice", as it were.

Remember that a table key can be *anything* (except nil and NaN),
including another table.

>
>
> here is the actual code:
>
>
> void OutputArchive::writeLuaTable(lua_State* l,int idx)
> {
>       lua_pushnil(l);
>       while(lua_next(l,idx)!=0)
>       {
>               const char* key=lua_tostring(l,-2);
>               int type=lua_type(l,-1);
>               switch(type)
>               {
>               case LUA_TNUMBER:
>                       writeByte(1);
>                       writeString(key);
>                       writeInt(type);
>                       writeDouble(lua_tonumber(l,-1));
>                       break;
>               case LUA_TSTRING:
>                       writeByte(1);
>                       writeString(key);
>                       writeInt(type);
>                       writeString(lua_tostring(l,-1));
>                       break;
>               case LUA_TBOOLEAN:
>                       writeByte(1);
>                       writeString(key);
>                       writeInt(type);
>                       writeBool(lua_toboolean(l,-1)!=0);
>                       break;
>               case LUA_TNIL:
>                       writeByte(1);
>                       writeString(key);
>                       writeInt(type);
>                       break;
>               case LUA_TTABLE:
>                       {
>                               writeByte(1);
>                               writeString(key);
>                               writeInt(type);
>                               writeLuaTable(l,lua_gettop(l));
>                       }
>                       break;
>               }
>               lua_pop(l,1);
>       }
> }
>
>
> void OutputArchive::writeLuaState(lua_State* l)
> {
>       writeLuaTable(l,LUA_GLOBALSINDEX);
> }
>
> On 1/19/07, Raymond Jacobs <raymondj@gmail.com> wrote:
>> Thanks for a quick reply =)
>>
>> I noticed I wasn't pushing the nil,
>>
>> my code now looks exactly like yours, but it's still error-ing;
>>
>> correct me if I'm wrong but,
>>
>>
>> when you go to recurse, you pass in an index of -1 for lua_next to
>> use, which is the top of the stack, yet in the function you then push
>> a nil, which is then at the top of the stack, thus using -1 to
>> reference the table would be wrong?
>>
>> -Raymond
>>
>> On 1/19/07, Jérôme VUARAND <jerome.vuarand@gmail.com> wrote:
>> > 2007/1/19, Raymond Jacobs <raymondj@gmail.com>:
>> > > int idx=LUA_GLOBALSINDEX;
>> > > lua_getfenv(l,idx);
>> > >
>> > > while(lua_next(l,idx)!=0)
>> > > {
>> > >                 const char* key=lua_tostring(l,-2);
>> > >
>> > >                 //get value at -1 index and check type of it
>> > >
>> > >                 //do somthing with key and value based on type of
>> value
>> > >                 //if value is a table call this function again to
>> traverse it, then
>> > > continue here
>> > >
>> > >
>> > >                 lua_pop(l,1);
>> > > }
>> > >
>> > > it seems in theory it should be as simple as doing another
>> lua_next,
>> > > however I've not been able to get it to work, and I end up
>> crashing,
>> > > likely due to corupting the stack; either my logic or how I'm
>> going
>> > > about it is wrong, an example of how to do this in the C API
>> would be
>> > > really helpful.
>> >
>> > You forget to push an initial nil on the stack before entering you
>> > while loop (see lua_next documentation example). Here is what your
>> > code could look like :
>> >
>> > int dosomestuff(lua_State* L, int index)
>> > {
>> >     // Do something with value at index (which is not a table)
>> >     return 1;
>> > }
>> >
>> > int parsetable(lua_State* L, int index)
>> > {
>> >     // Push an initial nil to init lua_next
>> >     lua_pushnil(L);
>> >     // Parse the table at index
>> >     while (lua_next(index)!=0)
>> >     {
>> >         if (lua_istable(L, -1)
>> >         {
>> >             parsetable(L, -1);
>> >         }
>> >         else
>> >         {
>> >             dosomestuff(L, -1);
>> >         }
>> >         // Pop value, keep key
>> >         lua_pop(L, 1);
>> >     }
>> >     return 1;
>> > }
>> >
>> > int parseglobals(lua_State* L)
>> > {
>> >     parsetable(L, LUA_GLOBALSINDEX);
>> >     return 0;
>> > }
>> >
>>