lua-users home
lua-l archive

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


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>