2 * lmo - Lua Machine Objects - Lua binding
4 * Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include "lmo_lualib.h"
21 extern char _lmo_error[1024];
24 static int lmo_L_open(lua_State *L) {
25 const char *filename = luaL_checklstring(L, 1, NULL);
26 lmo_archive_t *ar, **udata;
28 if( (ar = lmo_open(filename)) != NULL )
30 if( (udata = lua_newuserdata(L, sizeof(lmo_archive_t *))) != NULL )
33 luaL_getmetatable(L, LMO_ARCHIVE_META);
34 lua_setmetatable(L, -2);
40 lua_pushstring(L, "out of memory");
45 lua_pushstring(L, lmo_error());
49 static uint32_t _lmo_hash_string(lua_State *L, int n) {
51 const char *str = luaL_checklstring(L, n, &len);
55 if (!str || len >= sizeof(res))
58 while (*str && isspace(*str))
61 for (prev = 0, ptr = res; *str; prev = *str, str++)
76 while ((ptr > res) && isspace(*ptr))
79 return sfh_hash(res, ptr - res);
82 static int lmo_L_hash(lua_State *L) {
83 uint32_t hash = _lmo_hash_string(L, 1);
84 lua_pushinteger(L, (lua_Integer)hash);
88 static lmo_luaentry_t *_lmo_push_entry(lua_State *L) {
91 if( (le = lua_newuserdata(L, sizeof(lmo_luaentry_t))) != NULL )
93 luaL_getmetatable(L, LMO_ENTRY_META);
94 lua_setmetatable(L, -2);
102 static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
103 lmo_entry_t *e = ar->index;
104 lmo_luaentry_t *le = NULL;
108 if( e->key_id == hash )
110 if( (le = _lmo_push_entry(L)) != NULL )
119 lua_pushstring(L, "out of memory");
131 static int lmo_L_get(lua_State *L) {
132 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
133 uint32_t hash = (uint32_t) luaL_checkinteger(L, 2);
134 return _lmo_lookup(L, *ar, hash);
137 static int lmo_L_lookup(lua_State *L) {
138 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
139 uint32_t hash = _lmo_hash_string(L, 2);
140 return _lmo_lookup(L, *ar, hash);
143 static int lmo_L_foreach(lua_State *L) {
144 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
145 lmo_entry_t *e = (*ar)->index;
147 if( lua_isfunction(L, 2) )
152 lua_pushinteger(L, e->key_id);
153 lua_pushlstring(L, &(*ar)->mmap[e->offset], e->length);
154 lua_pcall(L, 2, 0, 0);
162 static int lmo_L__gc(lua_State *L) {
163 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
173 static int lmo_L__tostring(lua_State *L) {
174 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
175 lua_pushfstring(L, "LMO Archive (%d bytes)", (*ar)->length);
180 static int _lmo_convert_entry(lua_State *L, int idx) {
181 lmo_luaentry_t *le = luaL_checkudata(L, idx, LMO_ENTRY_META);
184 &le->archive->mmap[le->entry->offset],
191 static int lmo_L_entry__tostring(lua_State *L) {
192 return _lmo_convert_entry(L, 1);
195 static int lmo_L_entry__concat(lua_State *L) {
196 if( lua_isuserdata(L, 1) )
197 _lmo_convert_entry(L, 1);
199 lua_pushstring(L, lua_tostring(L, 1));
201 if( lua_isuserdata(L, 2) )
202 _lmo_convert_entry(L, 2);
204 lua_pushstring(L, lua_tostring(L, 2));
211 static int lmo_L_entry__len(lua_State *L) {
212 lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
213 lua_pushinteger(L, le->entry->length);
217 static int lmo_L_entry__gc(lua_State *L) {
218 lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
225 /* lmo method table */
226 static const luaL_reg M[] = {
227 {"close", lmo_L__gc},
229 {"lookup", lmo_L_lookup},
230 {"foreach", lmo_L_foreach},
231 {"__tostring", lmo_L__tostring},
236 /* lmo.entry method table */
237 static const luaL_reg E[] = {
238 {"__tostring", lmo_L_entry__tostring},
239 {"__concat", lmo_L_entry__concat},
240 {"__len", lmo_L_entry__len},
241 {"__gc", lmo_L_entry__gc},
246 static const luaL_reg R[] = {
247 {"open", lmo_L_open},
248 {"hash", lmo_L_hash},
252 LUALIB_API int luaopen_lmo(lua_State *L) {
253 luaL_newmetatable(L, LMO_ARCHIVE_META);
254 luaL_register(L, NULL, M);
255 lua_pushvalue(L, -1);
256 lua_setfield(L, -2, "__index");
257 lua_setglobal(L, LMO_ARCHIVE_META);
259 luaL_newmetatable(L, LMO_ENTRY_META);
260 luaL_register(L, NULL, E);
261 lua_pushvalue(L, -1);
262 lua_setfield(L, -2, "__index");
263 lua_setglobal(L, LMO_ENTRY_META);
265 luaL_register(L, LMO_LUALIB_META, R);