add some indirection around make targets of module.mk, so you can combine it more...
[project/luci.git] / libs / core / src / util.lua
1 --[[
2 LuCI - Utility library
3
4 Description:
5 Several common useful Lua functions
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at 
16
17         http://www.apache.org/licenses/LICENSE-2.0 
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26
27 module("luci.util", package.seeall)
28
29
30 -- Lua simplified Python-style OO class support emulation
31 function class(base)
32         local class = {}
33         
34         local create = function(class, ...)
35                 local inst = {}
36                 setmetatable(inst, {__index = class})
37                 
38                 if inst.__init__ then
39                         local stat, err = pcall(inst.__init__, inst, ...)
40                         if not stat then
41                                 error(err)
42                         end
43                 end
44                 
45                 return inst
46         end
47         
48         local classmeta = {__call = create}
49         
50         if base then
51                 classmeta.__index = base
52         end
53         
54         setmetatable(class, classmeta)
55         return class
56 end
57
58
59 -- Clones an object (deep on-demand)
60 function clone(object, deep)
61         local copy = {}
62         
63         for k, v in pairs(object) do
64                 if deep and type(v) == "table" then
65                         v = clone(v, deep)
66                 end
67                 copy[k] = v
68         end
69         
70         setmetatable(copy, getmetatable(object))
71         
72         return copy
73 end
74
75
76 -- Combines two or more numerically indexed tables into one
77 function combine(...)
78         local result = {}
79         for i, a in ipairs(arg) do
80                 for j, v in ipairs(a) do
81                         table.insert(result, v)
82                 end
83         end
84         return result
85 end
86
87
88 -- Checks whether a table has an object "value" in it
89 function contains(table, value)
90         for k,v in pairs(table) do
91                 if value == v then
92                         return true
93                 end
94         end
95         return false
96 end
97
98
99 -- Dumps a table to stdout (useful for testing and debugging)
100 function dumptable(t, i)
101         i = i or 0
102         for k,v in pairs(t) do
103                 print(string.rep("\t", i) .. k, v)
104                 if type(v) == "table" then
105                         dumptable(v, i+1)
106                 end
107         end
108 end
109
110
111 -- Escapes all occurences of c in s
112 function escape(s, c)
113         c = c or "\\"
114         return s:gsub(c, "\\" .. c)
115 end
116
117
118 -- Populate obj in the scope of f as key 
119 function extfenv(f, key, obj)
120         local scope = getfenv(f)
121         scope[key] = obj
122 end
123
124
125 -- Checks whether an object is an instanceof class
126 function instanceof(object, class)
127         local meta = getmetatable(object)
128     while meta and meta.__index do 
129         if meta.__index == class then
130                 return true
131         end
132         meta = getmetatable(meta.__index)
133     end
134     return false        
135 end
136
137
138 -- Creates valid XML PCDATA from a string
139 function pcdata(value)
140         value = value:gsub("&", "&amp;")        
141         value = value:gsub('"', "&quot;")
142         value = value:gsub("'", "&apos;")
143         value = value:gsub("<", "&lt;") 
144         return value:gsub(">", "&gt;")
145 end
146
147
148 -- Resets the scope of f doing a shallow copy of its scope into a new table
149 function resfenv(f)
150         setfenv(f, clone(getfenv(f)))
151 end 
152
153
154 -- Splits a string into an array
155 function split(str, pat, max, regex)
156         pat = pat or "\n"
157         max = max or #str
158         
159         local t = {}
160         local c = 1
161         
162         if #str == 0 then
163                 return {""}
164         end
165         
166         if #pat == 0 then
167                 return nil
168         end
169         
170         if max == 0 then
171                 return str
172         end
173         
174         repeat
175                 local s, e = str:find(pat, c, not regex)
176                 table.insert(t, str:sub(c, s and s - 1))
177                 max = max - 1
178                 c = e and e + 1 or #str + 1
179         until not s or max < 0
180         
181         return t
182 end
183
184 -- Removes whitespace from beginning and end of a string
185 function trim(str)
186         local s = str:gsub("^%s*(.-)%s*$", "%1")
187         return s
188 end
189
190 -- Updates given table with new values
191 function update(t, updates)
192         for k, v in pairs(updates) do
193                 t[k] = v
194         end     
195 end
196
197
198 -- Updates the scope of f with "extscope"
199 function updfenv(f, extscope)
200         update(getfenv(f), extscope)
201 end
202
203
204 -- Validates a variable
205 function validate(value, cast_number, cast_int)
206         if cast_number or cast_int then
207                 value = tonumber(value)
208         end
209         
210         if cast_int and value and not(value % 1 == 0) then
211                 value = nil
212         end
213         
214         return value
215 end