view C++/LuaeTable.h @ 225:e01ee0c72c43

Luae: begin refactoring of Luae
author David Demelier <markand@malikania.fr>
date Fri, 09 May 2014 17:12:25 +0200
parents
children
line wrap: on
line source

/*
 * LuaeTable.h -- Lua table helpers
 *
 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _LUAE_TABLE_H_
#define _LUAE_TABLE_H_

#include <lua.hpp>

/**
 * @class LuaeTable
 * @brief Some function for table manipulation
 *
 * Read, reference and get fields from tables.
 */
class LuaeTable {
public:
	/**
	 * The map function for \ref read
	 */
	using ReadFunction = std::function<void(lua_State *L, int tkey, int tvalue)>;

	/**
	 * Push a new table onto the stack.
	 *
	 * @param L the Lua state
	 * @param nrec the optional number of entries as record
	 * @param narr the optional number of entries as sequence
	 */
	static void create(lua_State *L, int nrec = 0, int narr = 0);

	/**
	 * Get a field of a specific type from a table. Specialized for the
	 * types: int, double, bool and string.
	 *
	 * @param L the Lua state
	 * @param idx the table index
	 * @param name the field name
	 * @return the converted type.
	 */
	template <typename T>
	static T get(lua_State *L, int idx, const std::string &name)
	{
		LUAE_STACK_CHECKBEGIN(L);

		lua_getfield(L, idx, name.c_str());
		auto t = Luae::get<T>(L, -1);
		lua_pop(L, 1);

		LUAE_STACK_CHECKEQUALS(L);

		return t;
	}

	/**
	 * Set a table field. Specialized for the same fields as get.
	 *
	 * @param L the Lua state
	 * @param idx the index
	 * @param name the field name
	 * @param value the value
	 * @see get
	 */
	template <typename T>
	static void set(lua_State *L, int idx, const std::string &name, const T &value)
	{
		LUAE_STACK_CHECKBEGIN(L);

		Luae::push(L, value);
		Luae::setfield(L, (idx < 0) ? --idx : idx, name);

		LUAE_STACK_CHECKEQUALS(L);
	}

	/**
	 * Overload for string literals.
	 *
	 * @param L the Lua state
	 * @param idx the index
	 * @param name the field name
	 * @param s the string
	 */
	template <size_t N>
	static void set(lua_State *L, int idx, const std::string &name, const char (&s)[N])
	{
		set<const char *>(L, idx, name, s);
	}

	/**
	 * Require a field from a table.
	 *
	 * @param L the Lua state
	 * @param idx the table index
	 * @param name the field name
	 * @return the value or call luaL_error
	 */
	template <typename T>
	static T require(lua_State *L, int idx, const std::string &name)
	{
		LUAE_STACK_CHECKBEGIN(L);

		lua_getfield(L, idx, name.c_str());

		if (lua_type(L, -1) == LUA_TNIL)
			luaL_error(L, "missing field `%s'", name.c_str());
			// NOT REACHED

		lua_pop(L, 1);
		auto v = get<T>(L, idx, name);

		LUAE_STACK_CHECKEQUALS(L);

		return v;
	}

	/**
	 * Check a table field.
	 *
	 * @param L the Lua state
	 * @param idx the table index
	 * @param name the field name
	 * @return the type
	 */
	static int type(lua_State *L, int idx, const std::string &name);

	/**
	 * Read a table, the function func is called for each element in the
	 * table. Parameter tkey is the Lua type of the key, parameter tvalue is
	 * the Lua type of the value. The key is available at index -2 and the
	 * value at index -1.
	 *
	 * <strong>Do not pop anything within the function.</strong>
	 *
	 * @param L the Lua state
	 * @param idx the table index
	 * @param func the function to call
	 */
	static void read(lua_State *L, int idx, ReadFunction func);

	/**
	 * Reference a field from a table at the index. The reference is created in
	 * the registry only if type matches.
	 *
	 * @param L the Lua state
	 * @param idx the table index
	 * @param type the type requested
	 * @param name the field name
	 * @return the reference or LUA_REFNIL on problem
	 */
	static int ref(lua_State *L,
		       int idx,
		       int type,
		       const std::string &name);
};

#endif // !_LUAE_TABLE_H_