libs/lmo: return entries as udata and only create strings on demand
This commit is contained in:
parent
639f965c4f
commit
3194662054
2 changed files with 103 additions and 9 deletions
|
@ -53,15 +53,40 @@ static int lmo_L_hash(lua_State *L) {
|
||||||
return 1;
|
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) {
|
static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
|
||||||
lmo_entry_t *e = ar->index;
|
lmo_entry_t *e = ar->index;
|
||||||
|
lmo_luaentry_t *le = NULL;
|
||||||
|
|
||||||
while( e != NULL )
|
while( e != NULL )
|
||||||
{
|
{
|
||||||
if( e->key_id == hash )
|
if( e->key_id == hash )
|
||||||
{
|
{
|
||||||
lua_pushlstring(L, &ar->mmap[e->offset], e->length);
|
if( (le = _lmo_push_entry(L)) != NULL )
|
||||||
return 1;
|
{
|
||||||
|
le->archive = ar;
|
||||||
|
le->entry = e;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, "out of memory");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e = e->next;
|
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[] = {
|
static const luaL_reg M[] = {
|
||||||
{"close", lmo_L__gc},
|
{"close", lmo_L__gc},
|
||||||
{"get", lmo_L_get},
|
{"get", lmo_L_get},
|
||||||
{"lookup", lmo_L_lookup},
|
{"lookup", lmo_L_lookup},
|
||||||
{"foreach", lmo_L_foreach},
|
{"foreach", lmo_L_foreach},
|
||||||
{"__tostring", lmo_L__tostring},
|
{"__tostring", lmo_L__tostring},
|
||||||
{"__gc", lmo_L__gc},
|
{"__gc", lmo_L__gc},
|
||||||
{NULL, NULL}
|
{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 */
|
/* module table */
|
||||||
|
@ -146,6 +225,12 @@ LUALIB_API int luaopen_lmo(lua_State *L) {
|
||||||
lua_setfield(L, -2, "__index");
|
lua_setfield(L, -2, "__index");
|
||||||
lua_setglobal(L, LMO_ARCHIVE_META);
|
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);
|
luaL_register(L, LMO_LUALIB_META, R);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -27,6 +27,15 @@
|
||||||
|
|
||||||
#define LMO_LUALIB_META "lmo"
|
#define LMO_LUALIB_META "lmo"
|
||||||
#define LMO_ARCHIVE_META "lmo.archive"
|
#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);
|
LUALIB_API int luaopen_lmo(lua_State *L);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue