lua-users home
lua-l archive

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


> 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;
}