[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua binding: How to implement C enum
- From: Patrick Rapin <toupie300@...>
- Date: Fri, 16 Dec 2011 09:14:24 +0100
> Did you use strtok? I remember some "strtok considered evil" or something...
No. The parsing is done manually in C with something like
"while(isalnum(*ptr++))".
It was not really difficult.
For information, I have joined the decoding code from Pipeline.
Don't expect however to use it without some modification...
My concern was not about performance. But I don't think the parsing is
that slow.
And, as Luiz pointed out, it is possible to cache values if the same
strings are used frequently.
typedef const char* PSTRING;
static int getEnumArgument(lua_State* L, int idx, PSTRING type, PSTRING def)
{
int t = lua_type(L, idx);
PSTRING valstr = NULL;
if(t == LUA_TNUMBER)
return (int)lua_tointeger(L, idx);
if(*def && (t == LUA_TNIL || t == LUA_TNONE))
valstr = def;
else if(t == LUA_TSTRING)
valstr = lua_tostring(L, idx);
else
luaL_error(L, "Expected enum value of type %s for index %d, got %s", type, idx, lua_typename(L, t));
int result = 0;
// Push a Lua table containing { ENUM = value, ...}
lua_getfield(L, LUA_REGISTRYINDEX, NewLibrary);
lua_getfield(L, -1, "enum");
luaL_checktype(L, -1, LUA_TTABLE);
lua_getfield(L, -1, type);
luaL_checktype(L, -1, LUA_TTABLE);
// Now the parsing
PSTRING pval = valstr;
bool negate = false;
while(1)
{
if(*pval == 0)
break;
if(*pval == '~')
negate = true;
if(!isalnum(*pval) && *pval != '_')
{
pval++;
continue;
}
PSTRING pnext = pval;
while(isalnum(*pnext) || *pnext == '_')
pnext++;
lua_pushlstring(L, pval, pnext-pval);
lua_gettable(L, -2);
if(!lua_isnumber(L, -1))
luaL_error(L, "Enum value '%s' not found in '%s'", valstr, type);
if(negate)
result &= ~lua_tointeger(L, -1);
else
result |= lua_tointeger(L, -1);
lua_pop(L, 1);
pval = pnext;
negate = false;
}
lua_pop(L, 3);
return result;
}