libs/lmo: check for integer, not number in lmo.archive.get()
[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 lmo_close(ar);
39 lua_pushnil(L);
40 lua_pushstring(L, "out of memory");
41 return 2;
42 }
43
44 lua_pushnil(L);
45 lua_pushstring(L, lmo_error());
46 return 2;
47 }
48
49 static int lmo_L_hash(lua_State *L) {
50 const char *data = luaL_checkstring(L, 1);
51 uint32_t hash = sfh_hash(data, strlen(data));
52 lua_pushinteger(L, (lua_Integer)hash);
53 return 1;
54 }
55
56 static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
57 lmo_entry_t *e = ar->index;
58
59 while( e != NULL )
60 {
61 if( e->key_id == hash )
62 {
63 lua_pushlstring(L, &ar->mmap[e->offset], e->length);
64 return 1;
65 }
66
67 e = e->next;
68 }
69
70 lua_pushnil(L);
71 return 1;
72 }
73
74 static int lmo_L_get(lua_State *L) {
75 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
76 uint32_t hash = (uint32_t) luaL_checkinteger(L, 2);
77 return _lmo_lookup(L, *ar, hash);
78 }
79
80 static int lmo_L_lookup(lua_State *L) {
81 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
82 const char *key = luaL_checkstring(L, 2);
83 uint32_t hash = sfh_hash(key, strlen(key));
84 return _lmo_lookup(L, *ar, hash);
85 }
86
87 static int lmo_L_foreach(lua_State *L) {
88 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
89 lmo_entry_t *e = (*ar)->index;
90
91 if( lua_isfunction(L, 2) )
92 {
93 while( e != NULL )
94 {
95 lua_pushvalue(L, 2);
96 lua_pushinteger(L, e->key_id);
97 lua_pushlstring(L, &(*ar)->mmap[e->offset], e->length);
98 lua_pcall(L, 2, 0, 0);
99 e = e->next;
100 }
101 }
102
103 return 0;
104 }
105
106 static int lmo_L__gc(lua_State *L) {
107 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
108
109 if( (*ar) != NULL )
110 lmo_close(*ar);
111
112 *ar = NULL;
113
114 return 0;
115 }
116
117 static int lmo_L__tostring(lua_State *L) {
118 lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
119 lua_pushfstring(L, "LMO Archive (%d bytes)", (*ar)->length);
120 return 1;
121 }
122
123
124 /* method table */
125 static const luaL_reg M[] = {
126 {"close", lmo_L__gc},
127 {"get", lmo_L_get},
128 {"lookup", lmo_L_lookup},
129 {"foreach", lmo_L_foreach},
130 {"__tostring", lmo_L__tostring},
131 {"__gc", lmo_L__gc},
132 {NULL, NULL}
133 };
134
135 /* module table */
136 static const luaL_reg R[] = {
137 {"open", lmo_L_open},
138 {"hash", lmo_L_hash},
139 {NULL, NULL}
140 };
141
142 LUALIB_API int luaopen_lmo(lua_State *L) {
143 luaL_newmetatable(L, LMO_ARCHIVE_META);
144 luaL_register(L, NULL, M);
145 lua_pushvalue(L, -1);
146 lua_setfield(L, -2, "__index");
147 lua_setglobal(L, LMO_ARCHIVE_META);
148
149 luaL_register(L, LMO_LUALIB_META, R);
150
151 return 1;
152 }