libs/lmo: return entries as udata and only create strings on demand

This commit is contained in:
Jo-Philipp Wich 2009-07-25 03:37:03 +00:00
parent 639f965c4f
commit 3194662054
2 changed files with 103 additions and 9 deletions

View file

@ -53,15 +53,40 @@ static int lmo_L_hash(lua_State *L) {
return 1;
}
static lmo_luaentry_t *_lmo_push_entry(lua_State *L) {
lmo_luaentry_t *le;
if( (le = lua_newuserdata(L, sizeof(lmo_luaentry_t))) != NULL )
{
luaL_getmetatable(L, LMO_ENTRY_META);
lua_setmetatable(L, -2);
return le;
}
return NULL;
}
static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
lmo_entry_t *e = ar->index;
lmo_luaentry_t *le = NULL;
while( e != NULL )
{
if( e->key_id == hash )
{
lua_pushlstring(L, &ar->mmap[e->offset], e->length);
return 1;
if( (le = _lmo_push_entry(L)) != NULL )
{
le->archive = ar;
le->entry = e;
return 1;
}
else
{
lua_pushnil(L);
lua_pushstring(L, "out of memory");
return 2;
}
}
e = e->next;
@ -121,15 +146,69 @@ static int lmo_L__tostring(lua_State *L) {
}
/* method table */
static int _lmo_convert_entry(lua_State *L, int idx) {
lmo_luaentry_t *le = luaL_checkudata(L, idx, LMO_ENTRY_META);
lua_pushlstring(L,
&le->archive->mmap[le->entry->offset],
le->entry->length
);
return 1;
}
static int lmo_L_entry__tostring(lua_State *L) {
return _lmo_convert_entry(L, 1);
}
static int lmo_L_entry__concat(lua_State *L) {
if( lua_isuserdata(L, 1) )
_lmo_convert_entry(L, 1);
else
lua_pushstring(L, lua_tostring(L, 1));
if( lua_isuserdata(L, 2) )
_lmo_convert_entry(L, 2);
else
lua_pushstring(L, lua_tostring(L, 2));
lua_concat(L, 2);
return 1;
}
static int lmo_L_entry__len(lua_State *L) {
lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
lua_pushinteger(L, le->entry->length);
return 1;
}
static int lmo_L_entry__gc(lua_State *L) {
lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
le->archive = NULL;
le->entry = NULL;
return 0;
}
/* lmo method table */
static const luaL_reg M[] = {
{"close", lmo_L__gc},
{"get", lmo_L_get},
{"lookup", lmo_L_lookup},
{"foreach", lmo_L_foreach},
{"close", lmo_L__gc},
{"get", lmo_L_get},
{"lookup", lmo_L_lookup},
{"foreach", lmo_L_foreach},
{"__tostring", lmo_L__tostring},
{"__gc", lmo_L__gc},
{NULL, NULL}
{"__gc", lmo_L__gc},
{NULL, NULL}
};
/* lmo.entry method table */
static const luaL_reg E[] = {
{"__tostring", lmo_L_entry__tostring},
{"__concat", lmo_L_entry__concat},
{"__len", lmo_L_entry__len},
{"__gc", lmo_L_entry__gc},
{NULL, NULL}
};
/* module table */
@ -146,6 +225,12 @@ LUALIB_API int luaopen_lmo(lua_State *L) {
lua_setfield(L, -2, "__index");
lua_setglobal(L, LMO_ARCHIVE_META);
luaL_newmetatable(L, LMO_ENTRY_META);
luaL_register(L, NULL, E);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setglobal(L, LMO_ENTRY_META);
luaL_register(L, LMO_LUALIB_META, R);
return 1;

View file

@ -27,6 +27,15 @@
#define LMO_LUALIB_META "lmo"
#define LMO_ARCHIVE_META "lmo.archive"
#define LMO_ENTRY_META "lmo.entry"
struct lmo_luaentry {
lmo_archive_t *archive;
lmo_entry_t *entry;
};
typedef struct lmo_luaentry lmo_luaentry_t;
LUALIB_API int luaopen_lmo(lua_State *L);