From 3194662054cebfefc48c7ff3d3a5d7a3aa988b9a Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sat, 25 Jul 2009 03:37:03 +0000 Subject: libs/lmo: return entries as udata and only create strings on demand --- libs/lmo/src/lmo_lualib.c | 103 ++++++++++++++++++++++++++++++++++++++++++---- libs/lmo/src/lmo_lualib.h | 9 ++++ 2 files changed, 103 insertions(+), 9 deletions(-) (limited to 'libs') diff --git a/libs/lmo/src/lmo_lualib.c b/libs/lmo/src/lmo_lualib.c index 676f788d2..59d88a15e 100644 --- a/libs/lmo/src/lmo_lualib.c +++ b/libs/lmo/src/lmo_lualib.c @@ -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; diff --git a/libs/lmo/src/lmo_lualib.h b/libs/lmo/src/lmo_lualib.h index 096fa027f..643511733 100644 --- a/libs/lmo/src/lmo_lualib.h +++ b/libs/lmo/src/lmo_lualib.h @@ -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); -- cgit v1.2.3