9f56c432b1acf1a46625914c2e5ac7582f797d81
[project/luci.git] / libs / core / src / luci_cutil.c
1 /**
2  * LuCI Core - Utility library
3  * Copyright (C) 2008 Steven Barth <steven@midlink.org>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "lauxlib.h"
19
20 #define LUCI_MODNAME "luci.cutil"
21 #define LUCI_MODDESC "LuCI Core Utility Library"
22 #define LUCI_MODCOPY "2008 Steven Barth"
23
24
25 /* Pythonic overloaded MOD operator */
26 static int luci__string_mod(lua_State *L) {
27         int i, n=1;
28
29         luaL_checkstring(L, 1);
30         luaL_checkany(L, 2);
31
32         /* Discard further arguments */
33         lua_settop(L, 2);
34
35         /* Get format and push it to the bottom of the stack */
36         lua_pushliteral(L, "");
37         lua_getfield(L, -1, "format");
38         lua_insert(L, 1);
39         lua_pop(L, 1);
40
41         /* If second argument is a table, unpack it */
42         if (lua_istable(L, 3)) {
43                 n = luaL_getn(L, 3);
44                 if (n > 0) {
45                         luaL_checkstack(L, n, "too many results to unpack");
46                         for (i=1; i<=n; i++) {
47                                 lua_rawgeti(L, 3, i);
48                         }
49                 } else {
50                         n = 0;
51                 }
52                 lua_remove(L, 3);
53         }
54
55         lua_call(L, n+1, 1);
56         return 1;
57 }
58
59 /* Instantiate a class */
60 static int luci__instantiate(lua_State *L) {
61         luaL_checktype(L, 1, LUA_TTABLE);
62
63         /* Create the object */
64         lua_newtable(L);
65
66         /* Create the metatable */
67         lua_createtable(L, 0, 1);
68         lua_pushvalue(L, 1);
69         lua_setfield(L, -2, "__index");
70         lua_setmetatable(L, -2);
71
72         /* Move instance at the bottom of the stack */
73         lua_replace(L, 1);
74
75         /* Invoke constructor if it exists */
76         lua_getfield(L, 1, "__init__");
77         if (lua_isfunction(L, -1)) {
78                 /* Put instance at the bottom for the 2nd time */
79                 lua_pushvalue(L, 1);
80                 lua_insert(L, 1);
81
82                 /* Call constructor */
83                 lua_insert(L, 2);
84                 lua_call(L, lua_gettop(L)-2, 0);
85         }
86
87         lua_settop(L, 1);
88         return 1;
89 }
90
91
92 /* luci.cutil.class(baseclass) */
93 static int luci_class(lua_State *L) {
94         int n = lua_gettop(L);
95
96         /* Create class */
97         lua_newtable(L);
98
99         /* Create metatable and register parent class if any */
100         if (n && lua_istable(L, 1)) {
101                 lua_createtable(L, 0, 2);
102                 lua_pushvalue(L, 1);
103                 lua_setfield(L, -2, "__index");
104         } else {
105                 lua_createtable(L, 0, 1);
106         }
107
108         /* Set instantiator */
109         lua_pushcfunction(L, luci__instantiate);
110         lua_setfield(L, -2, "__call");
111
112         lua_setmetatable(L, -2);
113         return 1;
114 }
115
116
117 /* Registry */
118 static const luaL_Reg registry[] = {
119                 {"class",               luci_class},
120                 { NULL,                 NULL },
121 };
122
123 /* Registrator */
124 LUALIB_API int luaopen_luci_cutil(lua_State *L) {
125         luaL_register(L, LUCI_MODNAME, registry);
126
127         lua_pushliteral(L, LUCI_MODDESC);
128         lua_setfield(L, -2, "_DESCRIPTION");
129
130         lua_pushliteral(L, LUCI_MODCOPY);
131         lua_setfield(L, -2, "_COPYRIGHT");
132
133
134         /* Register pythonic printf string operator */
135         lua_pushliteral(L, "");
136         lua_getmetatable(L, -1);
137         lua_pushcfunction(L, luci__string_mod);
138         lua_setfield(L, -2, "__mod");
139         lua_pop(L, 2);
140
141         return 1;
142 }