/*
* lmo - Lua Machine Objects - Lua binding
*
- * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ * Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return 1;
}
+ lmo_close(ar);
lua_pushnil(L);
lua_pushstring(L, "out of memory");
return 2;
return 2;
}
+static uint32_t _lmo_hash_string(lua_State *L, int n) {
+ size_t len;
+ const char *str = luaL_checklstring(L, n, &len);
+ char res[4096];
+ char *ptr, prev;
+
+ if (!str || len >= sizeof(res))
+ return 0;
+
+ while (*str && isspace(*str))
+ str++;
+
+ for (prev = 0, ptr = res; *str; prev = *str, str++)
+ {
+ if (isspace(*str))
+ {
+ if (isspace(prev))
+ continue;
+
+ *ptr++ = ' ';
+ }
+ else
+ {
+ *ptr++ = *str;
+ }
+ }
+
+ while ((ptr > res) && isspace(*ptr))
+ ptr--;
+
+ return sfh_hash(res, ptr - res);
+}
+
static int lmo_L_hash(lua_State *L) {
- const char *data = luaL_checkstring(L, 1);
- uint32_t hash = sfh_hash(data, strlen(data));
- lua_pushnumber(L, hash);
+ uint32_t hash = _lmo_hash_string(L, 1);
+ lua_pushinteger(L, (lua_Integer)hash);
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;
static int lmo_L_get(lua_State *L) {
lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- uint32_t hash = (uint32_t) luaL_checknumber(L, 2);
+ uint32_t hash = (uint32_t) luaL_checkinteger(L, 2);
return _lmo_lookup(L, *ar, hash);
}
static int lmo_L_lookup(lua_State *L) {
lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- const char *key = luaL_checkstring(L, 2);
- uint32_t hash = sfh_hash(key, strlen(key));
+ uint32_t hash = _lmo_hash_string(L, 2);
return _lmo_lookup(L, *ar, hash);
}
}
-/* 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 */
};
LUALIB_API int luaopen_lmo(lua_State *L) {
- luaL_newmetatable(L, LMO_LUALIB_META);
- luaL_register(L, NULL, R);
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- lua_setglobal(L, LMO_LUALIB_META);
-
luaL_newmetatable(L, LMO_ARCHIVE_META);
luaL_register(L, NULL, M);
lua_pushvalue(L, -1);
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;
}