lua-users home
lua-l archive

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


If worrying about speed, the answer is probably to stash a table or two somewhere that can be used to the string-to-enum and enum-to-string mappings. Say, for example, that you define your mapping in C code as something like (untested, uncompiled, written in e-mail, caveat, caveat, caveat):

typedef struct MappingEntry {
	const char* text;
	int value;
} MappingEntry;

static MappingEntry mapping[] = {
	{ "foo", (int) enumFoo },
	{ "baz", (int) enumBaz },
	{ NULL, 0 }
};

Then you can write C wrappers for converting enums:

	static void buildmapping( lua_State* L, MappingEntry* mapping ) {
		lua_newtable( L );
		for( ; mapping->text != NULL; ++mapping ) {
			lua_pushstring( L, mapping->text );			// table text
			lua_pushinteger( L, mapping->value );		// table text value
			lua_pushvalue( L, -1 );					// table text value value
			lua_pushvalue( L, -3 );					// table text value value text
			lua_settable( L, -5 );						// table text value
			lua_settable( L, -3 );						// table
		}
	}

	static void getmapping( lua_State* L, MappingEntry* mapping ) {

		lua_pushlightuserdata( L, mapping );
		lua_gettable( L, LUA_REGISTRYINDEX );

		if( lua_isnil( L, -1 ) ) {
			lua_pop( L, 1 );
			buildMappingTable( L, mapping );
			lua_pushlightuserdata( L, mapping );
			lua_pushvalue( L, -2 );
			lua_settable( L, LUA_REGISTRYINDEX );
		}

	}

	int checkenum( lua_State* L, int idx, MappingEntry* mapping ) {

		int result = 0;

		if( idx < 0 ) {
			int top = lua_gettop( L );
			if( 0 < idx + top + 1 )
				idx = idx + top + 1;
		}

		getmapping( L, mapping );
		lua_pushvalue( L, idx );
		lua_gettable( L, -2 );

		if( lua_type( L, -1 ) != LUA_TNUMBER ) {
			// Signal error here. We got a bad enum value
		}

		result = lua_tointeger( L, -1 );

		lua_pop( L, 2 );	// mapping and result

		return result;

	}


	void pushenum( lua_State* L, MappingEntry* mapping, int value ) {

		getmapping( L, mapping );
		lua_pushinteger( L, value );
		lua_gettable( L, -2 );
		lua_remove( L, -2 );	// mapping table

	}

In the push case, I suspect this pretty much always wins because it avoids rehashing the string. In the check case, the speed probably depends on how many enum values there are and how expensive the string comparisons are.

Mark