Jump to content
  • Advertisement
Sign in to follow this  
coolkehon

[Lua]Random Access Table Array

This topic is 3334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a table in lua like this
room = 
{
	start = { x=111; y=125; },
	bgcolor = "3399FF",
	bounds = 
	{
		{ x = 120; y = 72; },
		{ x = 192; y = 110; },
		{ x = 149; y = 134; },
		{ x = 182; y = 152; },
		{ x = 143; y = 172; },
		{ x = 161; y = 182; },
		{ x = 141; y = 193; },
		{ x = 25; y = 135; },
		{ x = 101; y = 96; },
		{ x = 88; y = 89; }
	};
}

and I need to be able to access the bounds at random such as x = bounds[5].x; but I need to do this from c/c++ I tried rawgeti but when I try get x or y it seg faults ex:
lua_rawgeti(m_state,-1,5);
lua_getfield(m_state,-1,"x");

is there another way to get random access to an array in lua from c/c++ [Edited by - coolkehon on October 24, 2009 5:58:44 PM]

Share this post


Link to post
Share on other sites
Advertisement
When you call rawgeti , is "bounds" at the top of the stack or is it "room"? if you forgot to index room to get bounds, that would cause nil. which may segfault if you index.

Also, why rawgeti? you're supposed to use that to bypass metamethods as far as I know.

Share this post


Link to post
Share on other sites
i first do lua_getglobal(m_state,-1,"room") so that room is on the top of the stack. Also I needed random access that is why I choose rawgeti because it's the only function I could find that would do so.

Is there another way to get value maybe such as


luaL_dostring(m_state,"room.bounds.x");
type val = lua_to*(m_state,-1);

Share this post


Link to post
Share on other sites
I made a dirty little hack. What do you think of it?


/** path == something like (room.bounds[1].x) */
std::string str = "return " + path;
luaL_dostring(m_state,str.c_str());



keep in mind (don't know if I said it already) but this is for a configuration lua script for the most part

Share this post


Link to post
Share on other sites
sorry for the extra post but here this is for anyone who might want to use it.
The license would be free to use for anyone and I'm completly not responsible for anything that happens. Commercial or whatever.

The code could use some cleanup of stuff where I comment out but it works and does what I want it to :)

LuaConfig.h

/*
* LuaConfig.h
*
* Created on: Oct 24, 2009
* Author: coolkehon
*/


#ifndef LUACONFIG_H_
#define LUACONFIG_H_

#include <lua.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>

class LuaConfig
{
private:
/** pointer to a lua state */
lua_State * m_state;
/** true if this owns the lua_State */
bool m_stown;
/** loads the path of a variable and adds it to the top of the stack
* @return true if loaded */

virtual bool loadPath(std::string path)
{
if(!m_state) return false;

// lua_pushstring(m_state,path.c_str());
std::string str = "return " + path;
luaL_dostring(m_state,str.c_str());

if(lua_isnoneornil(m_state,-1))
return false;
/** links to the path
* @example player.pos.start.x */

// std::vector<std::string> links;
// boost::split(links, path, boost::is_any_of(".[]"));
// if(links.size() <= 0)
// return false;
//// std::cout << "links = { \"";
// lua_getglobal(m_state,links[0].c_str());
// for(uint i = 1; i < links.size(); i++)
// {
//// std::cout << links << "\", \"";
//
// /** checks if all are digits and if so then it
// * means an index aka table[index] */

// boost::all(links,boost::is_digit()) ?
// lua_rawgeti(m_state,-1,atoi(links.c_str())) :
// lua_getfield(m_state,-1,links.c_str());
//
//
// if(lua_isnil(m_state,-1))
// {
// std::cout << "links[" << i << "] = nil\n";
// return false;
// }
// else
// std::cout << "found " << links << std::endl;
// }

// std::cout << " }" << std::endl;

return true;
}
public:
virtual ~LuaConfig()
{
if(m_state && m_stown)
lua_close(m_state);
}
LuaConfig(lua_State * state = NULL, bool own = false)
{
m_stown = own;
m_state = state;
}

/** checks if a given path exist */
virtual bool exist(std::string path)
{
if(!m_state) return false;
return loadPath(path);
}
/** looks up value at path and stores it in value
* @param path path to the lua variable
* @param value value to store the variable in
* @return true if found, false otherwise */

virtual bool lookupValue(std::string path, bool &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isboolean(m_state,-1))
{
value = lua_toboolean(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, int &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
{
value = lua_tonumber(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, std::string &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isstring(m_state,-1))
{
value = lua_tostring(m_state, -1) != NULL ? lua_tostring(m_state,-1) : "";
return true;
}
return false;
}
/** lookup the type of a path
* @return one of the lua type constants aka LUA_* */

virtual int getType(std::string path)
{
if(!m_state) return LUA_TNONE;
if(!loadPath(path)) return LUA_TNIL;
return lua_type(m_state,-1);
}
/** checks if a given path is a boolean */
virtual bool isBool(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isboolean(m_state,-1))
return true;
return false;
}
/** checks if a given path is a number */
virtual bool isNumber(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
return true;
return false;
}
/** checks if a given path is a string */
virtual bool isString(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isstring(m_state,-1))
return true;
return false;
}
};

#endif /* LUACONFIG_H_ */


Share this post


Link to post
Share on other sites
I made a C++ function that retrieves a number from any depth. It looks like this:
float& get_value(const size_t num_args, const char* key, ...) 
{
lua_getglobal(state, key);

// Go deeper, getting subtables as necessary
va_list key_list;
va_start(key_list, key);

size_t next = 1;
while(next++ < num_args)
{
lua_pushstring(state, va_arg(key_list, char*) );
lua_gettable(state, -2); // Q: Can this be done later?
}

va_end(key_list);

// store result in buffer, and clear Lua stack
output_value = lua_tonumber(state, -1);
lua_pop(state, num_args - 1);
return output_value;
};


But there's probably a more efficient way to grab the whole bounds table.

Share this post


Link to post
Share on other sites
the same way that I got the return value from lua for the random table param is how i got the size of the table. So this is the update LuaConfig.hpp

@note there may be bugs although I haven't had any and if so then fix them and post the fix please :D

cat LuaConfig.hpp
/*
* LuaConfig.hpp
*
* Created on: Oct 24, 2009
* Author: coolkehon
*/


#ifndef LUACONFIG_HPP_
#define LUACONFIG_HPP_

#include <lua.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>

class LuaConfig
{
private:
/** pointer to a lua state */
lua_State * m_state;
/** true if this owns the lua_State */
bool m_stown;
/** table
* @note wasn't sure what to call this
* @brief this is appended to any lookups so as to stay in a table */

std::string m_table;
/** loads the path of a variable and adds it to the top of the stack
* @return true if loaded */

virtual bool loadPath(std::string path)
{
if(!m_state) return false;

// lua_pushstring(m_state,path.c_str());
std::string str = "return " + path;
if(m_table.size() > 0)
str = "return " + m_table + "." + path;
luaL_dostring(m_state,str.c_str());

if(lua_isnoneornil(m_state,-1))
return false;
/** links to the path
* @example player.pos.start.x */

// std::vector<std::string> links;
// boost::split(links, path, boost::is_any_of(".[]"));
// if(links.size() <= 0)
// return false;
//// std::cout << "links = { \"";
// lua_getglobal(m_state,links[0].c_str());
// for(uint i = 1; i < links.size(); i++)
// {
//// std::cout << links << "\", \"";
//
// /** checks if all are digits and if so then it
// * means an index aka table[index] */

// boost::all(links,boost::is_digit()) ?
// lua_rawgeti(m_state,-1,atoi(links.c_str())) :
// lua_getfield(m_state,-1,links.c_str());
//
//
// if(lua_isnil(m_state,-1))
// {
// std::cout << "links[" << i << "] = nil\n";
// return false;
// }
// else
// std::cout << "found " << links << std::endl;
// }

// std::cout << " }" << std::endl;

return true;
}
public:
virtual ~LuaConfig()
{
if(m_state && m_stown)
lua_close(m_state);
}
LuaConfig(lua_State * state = NULL, bool own = false)
{
m_stown = own;
m_state = state;
m_table = "";
}

/** checks if a given path exist */
virtual bool exist(std::string path)
{
if(!m_state) return false;
return loadPath(path);
}
/** simply because libconfig spells it this way
* @brief the same as exist */

virtual bool exists(std::string path)
{
return exist(path);
}
/** looks up value at path and stores it in value
* @param path path to the lua variable
* @param value value to store the variable in
* @return true if found, false otherwise */

virtual bool lookupValue(std::string path, bool &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isboolean(m_state,-1))
{
value = lua_toboolean(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, int &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
{
value = lua_tonumber(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, uint32_t &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
{
value = lua_tonumber(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, std::string &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isstring(m_state,-1))
{
value = lua_tostring(m_state, -1) != NULL ? lua_tostring(m_state,-1) : "";
return true;
}
return false;
}
virtual bool lookupValue(std::string path, float &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
{
value = (float) lua_tonumber(m_state, -1);
return true;
}
return false;
}
virtual bool lookupValue(std::string path, double &value)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
{
value = (double) lua_tonumber(m_state, -1);
return true;
}
return false;
}
/** lookup the type of a path
* @return one of the lua type constants aka LUA_* */

virtual int getType(std::string path)
{
if(!m_state) return LUA_TNONE;
if(!loadPath(path)) return LUA_TNIL;
return lua_type(m_state,-1);
}
/** checks if a given path is a boolean */
virtual bool isBool(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isboolean(m_state,-1))
return true;
return false;
}
/** checks if a given path is a number */
virtual bool isNumber(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isnumber(m_state,-1))
return true;
return false;
}
/** checks if a given path is a string */
virtual bool isString(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_isstring(m_state,-1))
return true;
return false;
}
/** checks if a given path is a table */
virtual bool isTable(std::string path)
{
if(!m_state) return false;
if(!loadPath(path)) return false;

if(lua_istable(m_state,-1))
return true;
return false;
}
/** gets the size of a table */
virtual int getTableSize(std::string path)
{
if(!m_state) return 0;
if(!loadPath(path)) return 0;
if(!lua_istable(m_state,-1)) return 0;

std::string str;
m_table.size() > 0 ?
str = "return table.getn(" + m_table + "." + path + ")" :
str = "return table.getn(" + m_table + path + ")";
luaL_dostring(m_state,str.c_str());
return lua_tonumber(m_state,-1);
}
/** sets the current table for lookups
* @param path path to the table
* @return true on success */

virtual bool setCurTable(std::string path)
{
std::string oldpath = m_table;
m_table = "";
if(!isTable(path))
{
m_table = oldpath;
return false;
}
m_table = path;
return true;
}
/** return the current table path */
virtual std::string getCurTable()
{
return m_table;
}
};

#endif /* LUACONFIG_HPP_ */



Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!