lua-users home
lua-l archive

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

continuing an old thread...

I don't remember if anybody suggested solution for Chris question that was 
stable on (hypothetical) memory compacting GC and at the same time allowed 
for easy pointer comparison; but this is what i've just tried:

/*--------- string equality helper ------------*/
static int myStatKey;
static void regString (lua_State *L, const char *s) {

	lua_pushlightuserdata (L, myStatKey);
	lua_gettable (L, LUA_REGISTRYINDEX);
	if (lua_isnil (L, -1)) {
		lua_pop (L, 1);
		lua_newtable (L);
		lua_pushlightuserdata (L, myStatKey);
		lua_pushvalue (L, -2);
		lua_settable (L, LUA_REGISTRYINDEX);

	lua_pushstring (L, s);
	lua_pushlightuserdata (L, s);
	lua_settable (L, -3);

static const char *toStringReg (lua_State *L, int n) {
	const char *r = NULL;

	lua_pushlightuserdata (L, myStatKey);
	lua_gettable (L, LUA_REGISTRYINDEX);
	if (lua_isnil (L, -1)) {
		lua_pop (L, 1);
		return NULL;

	lua_pushvalue (L, n);
	lua_gettable (L, -2);

	r = lua_touserdata (L, -1);
	lua_pop (L, 1);

	return r;
/*------ end --------*/

the static int variable is used as a key in the registry, to avoid collisions.  
to use it, just register any constant string you'd like to use (at module 
initialization time):

	regString (L, "foo");
	regString (L, "bar");

and, in your  __index() metamethod (or anywhere you'd like to test a Lua 
string against several C strings), first convert it to the registered 

const char *k = *toStringReg (L, n);   /* n is a stack position */
if (k == "foo") {
	do_something ();
} else if (k == "bar") {
	do_someelse ():
} else {
	not_found ();

of course, this depends on the compiler optimizing equal constant strings to 
the same location in memory.

a little variation would be to store small integers (from an enum type) 
instead of the const char pointers. this would make possible to use  
switch(getreg(L,n)) {.....}


Attachment: pgpqxiDNf0wky.pgp
Description: PGP signature