[Lua]Random Access Table Array

Started by
5 comments, last by coolkehon 14 years, 5 months ago
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]
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.
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);
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
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_ */
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.
--"I'm not at home right now, but" = lights on, but no ones home
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_ */


This topic is closed to new replies.

Advertisement