[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Converting strings to enum values (C API)
- From: Tom N Harris <telliamed@...>
- Date: Tue, 10 Dec 2013 16:48:12 -0500
On Monday, December 09, 2013 11:26:40 AM Marc Lepage wrote:
> That seems to work well enough. Mapping tables stored in the registry.
> Would it be beneficial to use upvalues instead? (Pros/cons? Performance?) I
> haven't really done upvalues from C, I will check the docs.
This is how I did a simple string to number converter.
typedef struct EnumVal { const char *s; int v; } EnumVal;
static int s_enumvalue(const char* name, const EnumVal * lst) {
int idx;
for (idx=0; lst[idx].s; idx++)
if (strcmp(lst[idx].s, name) == 0)
return idx;
return -1;
}
static int l_enumvalue(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
/* Lookup name in memo table */
lua_pushvalue(L, 1);
lua_gettable(L, lua_upvalueindex(1));
if (lua_isnil(L, -1)) {
/* Lookup name in static struct */
const EnumVal * lst = lua_touserdata(L, lua_upvalueindex(2));
int idx = s_enumvalue(name, lst);
if (idx != -1) {
lua_pop(L, 1); /* remove nil from lua_gettable */
/* Memoize */
lua_pushinteger(L, lst[idx].v);
lua_pushvalue(L, 1);
lua_pushvalue(L, -2);
lua_settable(L, lua_upvalueindex(1));
}
/* else unknown, return nil (already on stack) */
}
return 1;
}
int new_enumerator(lua_State *L, const EnumVal enums []) {
lua_newtable(L);
lua_pushlightuserdata(L, (void*)enums);
lua_pushcclosure(L, l_enumvalue, 2);
return 1;
}
Going from numbers to strings probably doesn't need a Lua table. If the
enumeration is consecutive numbers, a C array is fastest. Or just use a switch
statement which the compiler will turn into a jump table. But then you have to
each name/value twice, in the array and again in the switch. If you have a lot
of them and want to use an automated API generator, building Lua tables ahead
of time will make your code look cleaner. Just have `reg_lut` return the
getter and setter table on the Lua stack then push each closure taking the
upvalue instead of reading the registry.
--
tom <telliamed@whoopdedo.org>