lua-users home
lua-l archive

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


I suppose these have been posted many times before, but I'm not quite sure
how to search for them. Anyone care to comment on these utility functions?
This implementation assumes C99, so one needn't worry about the NULL
terminator, otherwise just remove the macro interpostions. These extend
lua_getfield and lua_setfield for nested table manipulation. (The 'Z' is
because it comes from my Zoned project.) Use is like:

/* some and/or table will be "autovivified" */
lua_pushinteger(L, 42);
luaZ_setglobal(L, "some", "table, "value");

luaZ_getglobal(L, "some", "table", "value");

printf("answer: %d\n", lua_tointeger(L, -1));



/* .h */

void luaZ_setfield(lua_State *, int, const char *, ...);

#define luaZ_setfield(L, ...)	luaZ_setfield((L), __VA_ARGS__, (const char *)0)

#define luaZ_setglobal(L, ...)	luaZ_setfield((L), LUA_GLOBALSINDEX, __VA_ARGS__)


/* .c */

#undef luaZ_getfield

void luaZ_getfield(lua_State *L, int index, const char *name, ...) {
	const char *next;
	va_list ap;

	va_start(ap, name);

	lua_getfield(L, index, name);

	while (0 != (next = va_arg(ap, const char *)) && !lua_isnil(L, -1)) {
		if (lua_istable(L, -1)) {
			lua_getfield(L, -1, next);
		} else
			lua_pushnil(L);

		lua_replace(L, -2);
	}

	va_end(ap);

	return /* void */;
} /* luaZ_getfield() */


#undef luaZ_setfield

void luaZ_setfield(lua_State *L, int index, const char *name, ...) {
	const char *next, *prev	= "?";
	va_list ap;

	/* put our table at the top so we can start properly */ 
	lua_pushvalue(L, index);

	va_start(ap, name);

	while (0 != (next = va_arg(ap, const char *))) {
		lua_getfield(L, -1, name);

		switch (lua_type(L, -1)) {
		case LUA_TNIL:
			lua_pop(L, 1);

			lua_newtable(L);
				lua_pushvalue(L, -1);
				lua_setfield(L, -3, name);

			/* FALL THROUGH */
		case LUA_TTABLE:
			break;
		default:
			luaL_error(L, "not a table: %s (%s)", name, luaL_typename(L, -1));

			return /* void */;
		}

		lua_replace(L, -2);

		prev	= name;
		name	= next;
	}

	if (!lua_istable(L, -1))
		luaL_error(L, "not a table: %s (%s)", prev, luaL_typename(L, -1));

	lua_pushvalue(L, -2);
	lua_setfield(L, -2, name);

	va_end(ap);

	lua_pop(L, 2);	/* table and value */

	return /* void */;
} /* luaZ_setfield() */