878ca02b2700d671f0cbd9a0a701033b963da05f
[project/luci.git] / libs / lmo / src / lmo_lualib.c
1 /*
2  * lmo - Lua Machine Objects - Lua binding
3  *
4  *   Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include "lmo_lualib.h"
20
21 extern char _lmo_error[1024];
22
23
24 static int lmo_L_open(lua_State *L) {
25         const char *filename = luaL_checklstring(L, 1, NULL);
26         lmo_archive_t *ar, **udata;
27
28         if( (ar = lmo_open(filename)) != NULL )
29         {
30                 if( (udata = lua_newuserdata(L, sizeof(lmo_archive_t *))) != NULL )
31                 {
32                         *udata = ar;
33                         luaL_getmetatable(L, LMO_ARCHIVE_META);
34                         lua_setmetatable(L, -2);
35                         return 1;
36                 }
37
38                 lua_pushnil(L);
39                 lua_pushstring(L, "out of memory");
40                 return 2;
41         }
42
43         lua_pushnil(L);
44         lua_pushstring(L, lmo_error());
45         return 2;
46 }
47
48 static int lmo_L_hash(lua_State *L) {
49         const char *data = luaL_checkstring(L, 1);
50         uint32_t hash = sfh_hash(data, strlen(data));
51         lua_pushnumber(L, hash);
52         return 1;
53 }
54
55 static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
56         lmo_entry_t *e = ar->index;
57
58         while( e != NULL )
59         {
60                 if( e->key_id == hash )
61                 {
62                         lua_pushlstring(L, &ar->mmap[e->offset], e->length);
63                         return 1;
64                 }
65
66                 e = e->next;
67         }
68
69         lua_pushnil(L);
70         return 1;
71 }
72
73 static int lmo_L_get(lua_State *L) {
74         lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
75         uint32_t hash = (uint32_t) luaL_checknumber(L, 2);
76         return _lmo_lookup(L, *ar, hash);
77 }
78
79 static int lmo_L_lookup(lua_State *L) {
80         lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
81         const char *key = luaL_checkstring(L, 2);
82         uint32_t hash = sfh_hash(key, strlen(key));
83         return _lmo_lookup(L, *ar, hash);
84 }
85
86 static int lmo_L_foreach(lua_State *L) {
87         lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
88         lmo_entry_t *e = (*ar)->index;
89
90         if( lua_isfunction(L, 2) )
91         {
92                 while( e != NULL )
93                 {
94                         lua_pushvalue(L, 2);
95                         lua_pushinteger(L, e->key_id);
96                         lua_pushlstring(L, &(*ar)->mmap[e->offset], e->length);
97                         lua_pcall(L, 2, 0, 0);
98                         e = e->next;
99                 }
100         }
101
102         return 0;
103 }
104
105 static int lmo_L__gc(lua_State *L) {
106         lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
107
108         if( (*ar) != NULL )
109                 lmo_close(*ar);
110
111         *ar = NULL;
112
113         return 0;
114 }
115
116 static int lmo_L__tostring(lua_State *L) {
117         lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
118         lua_pushfstring(L, "LMO Archive (%d bytes)", (*ar)->length);
119         return 1;
120 }
121
122
123 /* method table */
124 static const luaL_reg M[] = {
125         {"close",       lmo_L__gc},
126         {"get",         lmo_L_get},
127         {"lookup",      lmo_L_lookup},
128         {"foreach",     lmo_L_foreach},
129         {"__tostring",  lmo_L__tostring},
130         {"__gc",        lmo_L__gc},
131         {NULL,          NULL}
132 };
133
134 /* module table */
135 static const luaL_reg R[] = {
136         {"open",        lmo_L_open},
137         {"hash",        lmo_L_hash},
138         {NULL,          NULL}
139 };
140
141 LUALIB_API int luaopen_lmo(lua_State *L) {
142         luaL_newmetatable(L, LMO_LUALIB_META);
143         luaL_register(L, NULL, R);
144         lua_pushvalue(L, -1);
145         lua_setfield(L, -2, "__index");
146         lua_setglobal(L, LMO_LUALIB_META);
147
148         luaL_newmetatable(L, LMO_ARCHIVE_META);
149         luaL_register(L, NULL, M);
150         lua_pushvalue(L, -1);
151         lua_setfield(L, -2, "__index");
152         lua_setglobal(L, LMO_ARCHIVE_META);
153
154         return 1;
155 }