General optimizations, simplifications and improvements
[project/luci.git] / libs / core / luasrc / 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 local io = require "io"
28 local table = require "table"
29 local debug = require "debug"
30 local string = require "string"
31 local coroutine = require "coroutine"
32
33 local getmetatable, setmetatable = getmetatable, setmetatable
34 local getfenv, setfenv = getfenv, setfenv
35 local rawget, rawset, unpack = rawget, rawset, unpack
36 local tostring, type, assert = tostring, type, assert 
37 local ipairs, pairs, loadstring = ipairs, pairs, loadstring
38 local require, pcall, xpcall = require, pcall, xpcall
39
40 --- LuCI utility functions.
41 module "luci.util"
42
43 --
44 -- Pythonic string formatting extension
45 --
46 getmetatable("").__mod = function(a, b)
47         if not b then
48                 return a
49         elseif type(b) == "table" then
50                 return a:format(unpack(b))
51         else
52                 return a:format(b)
53         end
54 end
55
56
57 --
58 -- Class helper routines
59 --
60
61 --- Create a Class object (Python-style object model).
62 -- The class object can be instantiated by calling itself.
63 -- Any class functions or shared parameters can be attached to this object.
64 -- Attaching a table to the class object makes this table shared between
65 -- all instances of this class. For object parameters use the __init__ function.
66 -- Classes can inherit member functions and values from a base class.
67 -- Class can be instantiated by calling them. All parameters will be passed
68 -- to the __init__ function of this class - if such a function exists.
69 -- The __init__ function must be used to set any object parameters that are not shared
70 -- with other objects of this class. Any return values will be ignored.
71 -- @param base  The base class to inherit from (optional)
72 -- @return              A class object
73 -- @see                 instanceof
74 -- @see                 clone
75 function class(base)
76         local class = {}
77
78         local create = function(class, ...)
79                 local inst = setmetatable({}, {__index = class})
80
81                 if inst.__init__ then
82                         inst:__init__(...)
83                 end
84
85                 return inst
86         end
87
88         local classmeta = {__call = create}
89
90         if base then
91                 classmeta.__index = base
92         end
93
94         setmetatable(class, classmeta)
95         return class
96 end
97
98 --- Test whether the given object is an instance of the given class.
99 -- @param object        Object instance
100 -- @param class         Class object to test against
101 -- @return                      Boolean indicating whether the object is an instance
102 -- @see                         class
103 -- @see                         clone
104 function instanceof(object, class)
105         local meta = getmetatable(object)
106         while meta and meta.__index do
107                 if meta.__index == class then
108                         return true
109                 end
110                 meta = getmetatable(meta.__index)
111         end
112         return false
113 end
114
115
116 --
117 -- Scope manipulation routines
118 --
119
120 --- Replace a function scope with a shallow copy of itself.
121 -- This is useful if you want to get rid of several unwanted side effects
122 -- while changing the scope of a certain Lua function.
123 -- @param f             Lua function
124 function resfenv(f)
125         setfenv(f, clone(getfenv(f)))
126 end
127
128 --- Store given object associated with given key in the scope of a function.
129 -- @param f             Lua function
130 -- @param key   String value containg the key of the object to store
131 -- @param obj   Object to store in the scope
132 -- @return              Always nil
133 -- @see updfenv
134 -- @see resfenv
135 function extfenv(f, key, obj)
136         local scope = getfenv(f)
137         scope[key] = obj
138 end
139
140 --- Extend the scope of a function with the contents of a table
141 -- @param f             Lua function
142 -- @param key   String value containg the key of the object to store
143 -- @param obj   Object to store in the scope
144 -- @return              Always nil
145 -- @see extfenv
146 -- @see resfenv
147 function updfenv(f, extscope)
148         update(getfenv(f), extscope)
149 end
150
151 --- Create a new or get an already existing thread local store associated with
152 -- the current active coroutine. A thread local store is private a table object
153 -- whose values can't be accessed from outside of the running coroutine.
154 -- @return      Table value representing the corresponding thread local store
155 function threadlocal()
156         local tbl = {}
157
158         local function get(self, key)
159                 local c = coroutine.running()
160                 local thread = coxpt[c] or c or 0
161                 if not rawget(self, thread) then
162                         return nil
163                 end
164                 return rawget(self, thread)[key]
165         end
166
167         local function set(self, key, value)
168                 local c = coroutine.running()
169                 local thread = coxpt[c] or c or 0
170                 if not rawget(self, thread) then
171                         rawset(self, thread, {})
172                 end
173                 rawget(self, thread)[key] = value
174         end
175
176         setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"})
177
178         return tbl
179 end
180
181
182 --
183 -- Debugging routines
184 --
185
186 --- Write given object to stderr.
187 -- @param obj   Value to write to stderr
188 -- @return              Boolean indicating whether the write operation was successful
189 function perror(obj)
190         return io.stderr:write(tostring(obj) .. "\n")
191 end
192
193 --- Recursively dumps a table to stdout, useful for testing and debugging.
194 -- @param t     Table value to dump
195 -- @param maxdepth      Maximum depth
196 -- @return      Always nil
197 function dumptable(t, maxdepth, i, seen)
198         i = i or 0
199         seen = seen or setmetatable({}, {__mode="k"})
200         
201         for k,v in pairs(t) do
202                 perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
203                 if type(v) == "table" and (not maxdepth or i < maxdepth) then
204                         if not seen[v] then
205                                 seen[v] = true
206                                 dumptable(v, maxdepth, i+1, seen)
207                         else
208                                 perror(string.rep("\t", i) .. "*** RECURSION ***")
209                         end
210                 end
211         end
212 end
213
214
215 --
216 -- String and data manipulation routines
217 --
218
219 --- Escapes all occurrences of the given character in given string.
220 -- @param s     String value containing unescaped characters
221 -- @param c     String value with character to escape (optional, defaults to "\")
222 -- @return      String value with each occurrence of character escaped with "\"
223 function escape(s, c)
224         c = c or "\\"
225         return s:gsub(c, "\\" .. c)
226 end
227
228 --- Create valid XML PCDATA from given string.
229 -- @param value String value containing the data to escape
230 -- @return              String value containing the escaped data
231 function pcdata(value)
232         if not value then return end
233         value = tostring(value)
234         value = value:gsub("&", "&amp;")
235         value = value:gsub('"', "&quot;")
236         value = value:gsub("'", "&apos;")
237         value = value:gsub("<", "&lt;")
238         return value:gsub(">", "&gt;")
239 end
240
241 --- Strip HTML tags from given string.
242 -- @param value String containing the HTML text
243 -- @return      String with HTML tags stripped of
244 function striptags(s)
245         return pcdata(s:gsub("</?[A-Za-z][A-Za-z0-9:_%-]*[^>]*>", " "):gsub("%s+", " "))
246 end
247
248 --- Splits given string on a defined separator sequence and return a table
249 -- containing the resulting substrings. The optional max parameter specifies
250 -- the number of bytes to process, regardless of the actual length of the given
251 -- string. The optional last parameter, regex, specifies whether the separator
252 -- sequence is interpreted as regular expression.
253 -- @param str           String value containing the data to split up
254 -- @param pat           String with separator pattern (optional, defaults to "\n")
255 -- @param max           Maximum times to split (optional)
256 -- @param regex         Boolean indicating whether to interpret the separator
257 --                                      pattern as regular expression (optional, default is false)
258 -- @return                      Table containing the resulting substrings
259 function split(str, pat, max, regex)
260         pat = pat or "\n"
261         max = max or #str
262
263         local t = {}
264         local c = 1
265
266         if #str == 0 then
267                 return {""}
268         end
269
270         if #pat == 0 then
271                 return nil
272         end
273
274         if max == 0 then
275                 return str
276         end
277
278         repeat
279                 local s, e = str:find(pat, c, not regex)
280                 max = max - 1
281                 if s and max < 0 then
282                         table.insert(t, str:sub(c))
283                 else
284                         table.insert(t, str:sub(c, s and s - 1))
285                 end
286                 c = e and e + 1 or #str + 1
287         until not s or max < 0
288
289         return t
290 end
291
292 --- Remove leading and trailing whitespace from given string value.
293 -- @param str   String value containing whitespace padded data
294 -- @return              String value with leading and trailing space removed
295 function trim(str)
296         return (str:gsub("^%s*(.-)%s*$", "%1"))
297 end
298
299 --- Parse certain units from the given string and return the canonical integer
300 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
301 -- Recognized units are:
302 --      o "y"   - one year   (60*60*24*366)
303 --  o "m"       - one month  (60*60*24*31)
304 --  o "w"       - one week   (60*60*24*7)
305 --  o "d"       - one day    (60*60*24)
306 --  o "h"       - one hour       (60*60)
307 --  o "min"     - one minute (60)
308 --  o "kb"  - one kilobyte (1024)
309 --  o "mb"      - one megabyte (1024*1024)
310 --  o "gb"      - one gigabyte (1024*1024*1024)
311 --  o "kib" - one si kilobyte (1000)
312 --  o "mib"     - one si megabyte (1000*1000)
313 --  o "gib"     - one si gigabyte (1000*1000*1000)
314 -- @param ustr  String containing a numerical value with trailing unit
315 -- @return              Number containing the canonical value
316 function parse_units(ustr)
317
318         local val = 0
319
320         -- unit map
321         local map = {
322                 -- date stuff
323                 y   = 60 * 60 * 24 * 366,
324                 m   = 60 * 60 * 24 * 31,
325                 w   = 60 * 60 * 24 * 7,
326                 d   = 60 * 60 * 24,
327                 h   = 60 * 60,
328                 min = 60,
329
330                 -- storage sizes
331                 kb  = 1024,
332                 mb  = 1024 * 1024,
333                 gb  = 1024 * 1024 * 1024,
334
335                 -- storage sizes (si)
336                 kib = 1000,
337                 mib = 1000 * 1000,
338                 gib = 1000 * 1000 * 1000
339         }
340
341         -- parse input string
342         for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
343
344                 local num = spec:gsub("[^0-9%.]+$","")
345                 local spn = spec:gsub("^[0-9%.]+", "")
346
347                 if map[spn] or map[spn:sub(1,1)] then
348                         val = val + num * ( map[spn] or map[spn:sub(1,1)] )
349                 else
350                         val = val + num
351                 end
352         end
353
354
355         return val
356 end
357
358 --- Combines two or more numerically indexed tables into one.
359 -- @param tbl1  Table value to combine
360 -- @param tbl2  Table value to combine
361 -- @param ...   More tables to combine
362 -- @return              Table value containing all values of given tables
363 function combine(...)
364         local result = {}
365         for i, a in ipairs(arg) do
366                 for j, v in ipairs(a) do
367                         table.insert(result, v)
368                 end
369         end
370         return result
371 end
372
373 --- Checks whether the given table contains the given value.
374 -- @param table Table value
375 -- @param value Value to search within the given table
376 -- @return              Boolean indicating whether the given value occurs within table
377 function contains(table, value)
378         for k, v in pairs(table) do
379                 if value == v then
380                         return k
381                 end
382         end
383         return false
384 end
385
386 --- Update values in given table with the values from the second given table.
387 -- Both table are - in fact - merged together.
388 -- @param t                     Table which should be updated
389 -- @param updates       Table containing the values to update
390 -- @return                      Always nil
391 function update(t, updates)
392         for k, v in pairs(updates) do
393                 t[k] = v
394         end
395 end
396
397 --- Retrieve all keys of given associative table.
398 -- @param t     Table to extract keys from
399 -- @return      Sorted table containing the keys
400 function keys(t)
401         local keys = { }
402         if t then
403                 for k, _ in kspairs(t) do
404                         table.insert( keys, k )
405                 end
406         end
407         return keys
408 end
409
410 --- Clones the given object and return it's copy.
411 -- @param object        Table value to clone
412 -- @param deep          Boolean indicating whether to do recursive cloning
413 -- @return                      Cloned table value
414 function clone(object, deep)
415         local copy = {}
416
417         for k, v in pairs(object) do
418                 if deep and type(v) == "table" then
419                         v = clone(v, deep)
420                 end
421                 copy[k] = v
422         end
423
424         return setmetatable(copy, getmetatable(object))
425 end
426
427
428 --- Create a dynamic table which automatically creates subtables.
429 -- @return      Dynamic Table
430 function dtable()
431         return setmetatable({}, { __index =
432                 function(tbl, key)
433                         return rawget(tbl, key)
434                          or rawget(rawset(tbl, key, dtable()), key)
435                 end
436         })
437 end
438
439
440 -- Serialize the contents of a table value.
441 function _serialize_table(t, seen)
442         assert(not seen[t], "Recursion detected.")
443         seen[t] = true
444         
445         local data  = ""
446         local idata = ""
447         local ilen  = 0
448
449         for k, v in pairs(t) do
450                 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
451                         k = serialize_data(k, seen)
452                         v = serialize_data(v, seen)
453                         data = data .. ( #data > 0 and ", " or "" ) ..
454                                 '[' .. k .. '] = ' .. v
455                 elseif k > ilen then
456                         ilen = k
457                 end
458         end
459
460         for i = 1, ilen do
461                 local v = serialize_data(t[i], seen)
462                 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
463         end             
464
465         return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
466 end
467
468 --- Recursively serialize given data to lua code, suitable for restoring
469 -- with loadstring().
470 -- @param val   Value containing the data to serialize
471 -- @return              String value containing the serialized code
472 -- @see                 restore_data
473 -- @see                 get_bytecode
474 function serialize_data(val, seen)
475         seen = seen or setmetatable({}, {__mode="k"})
476         
477         if val == nil then
478                 return "nil"
479         elseif type(val) == "number" then
480                 return val
481         elseif type(val) == "string" then
482                 return "%q" % val
483         elseif type(val) == "boolean" then
484                 return val and "true" or "false"
485         elseif type(val) == "function" then
486                 return "loadstring(%q)" % get_bytecode(val)
487         elseif type(val) == "table" then
488                 return "{ " .. _serialize_table(val, seen) .. " }"
489         else
490                 return '"[unhandled data type:' .. type(val) .. ']"'
491         end
492 end
493
494 --- Restore data previously serialized with serialize_data().
495 -- @param str   String containing the data to restore
496 -- @return              Value containing the restored data structure
497 -- @see                 serialize_data
498 -- @see                 get_bytecode
499 function restore_data(str)
500         return loadstring("return " .. str)()
501 end
502
503
504 --
505 -- Byte code manipulation routines
506 --
507
508 --- Return the current runtime bytecode of the given data. The byte code
509 -- will be stripped before it is returned.
510 -- @param val   Value to return as bytecode
511 -- @return              String value containing the bytecode of the given data
512 function get_bytecode(val)
513         local code
514
515         if type(val) == "function" then
516                 code = string.dump(val)
517         else
518                 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
519         end
520
521         return code and strip_bytecode(code)
522 end
523
524 --- Strips unnescessary lua bytecode from given string. Information like line
525 -- numbers and debugging numbers will be discarded. Original version by
526 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
527 -- @param code  String value containing the original lua byte code
528 -- @return              String value containing the stripped lua byte code
529 function strip_bytecode(code)
530         local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
531         local subint
532         if endian == 1 then
533                 subint = function(code, i, l)
534                         local val = 0
535                         for n = l, 1, -1 do
536                                 val = val * 256 + code:byte(i + n - 1)
537                         end
538                         return val, i + l
539                 end
540         else
541                 subint = function(code, i, l)
542                         local val = 0
543                         for n = 1, l, 1 do
544                                 val = val * 256 + code:byte(i + n - 1)
545                         end
546                         return val, i + l
547                 end
548         end
549
550         local strip_function
551         strip_function = function(code)
552                 local count, offset = subint(code, 1, size)
553                 local stripped, dirty = string.rep("\0", size), offset + count
554                 offset = offset + count + int * 2 + 4
555                 offset = offset + int + subint(code, offset, int) * ins
556                 count, offset = subint(code, offset, int)
557                 for n = 1, count do
558                         local t
559                         t, offset = subint(code, offset, 1)
560                         if t == 1 then
561                                 offset = offset + 1
562                         elseif t == 4 then
563                                 offset = offset + size + subint(code, offset, size)
564                         elseif t == 3 then
565                                 offset = offset + num
566                         elseif t == 254 or t == 9 then
567                                 offset = offset + lnum
568                         end
569                 end
570                 count, offset = subint(code, offset, int)
571                 stripped = stripped .. code:sub(dirty, offset - 1)
572                 for n = 1, count do
573                         local proto, off = strip_function(code:sub(offset, -1))
574                         stripped, offset = stripped .. proto, offset + off - 1
575                 end
576                 offset = offset + subint(code, offset, int) * int + int
577                 count, offset = subint(code, offset, int)
578                 for n = 1, count do
579                         offset = offset + subint(code, offset, size) + size + int * 2
580                 end
581                 count, offset = subint(code, offset, int)
582                 for n = 1, count do
583                         offset = offset + subint(code, offset, size) + size
584                 end
585                 stripped = stripped .. string.rep("\0", int * 3)
586                 return stripped, offset
587         end
588
589         return code:sub(1,12) .. strip_function(code:sub(13,-1))
590 end
591
592
593 --
594 -- Sorting iterator functions
595 --
596
597 function _sortiter( t, f )
598         local keys = { }
599
600         for k, v in pairs(t) do
601                 table.insert( keys, k )
602         end
603
604         local _pos = 0
605         local _len = table.getn( keys )
606
607         table.sort( keys, f )
608
609         return function()
610                 _pos = _pos + 1
611                 if _pos <= _len then
612                         return keys[_pos], t[keys[_pos]]
613                 end
614         end
615 end
616
617 --- Return a key, value iterator which returns the values sorted according to
618 -- the provided callback function.
619 -- @param t     The table to iterate
620 -- @param f A callback function to decide the order of elements
621 -- @return      Function value containing the corresponding iterator
622 function spairs(t,f)
623         return _sortiter( t, f )
624 end
625
626 --- Return a key, value iterator for the given table.
627 -- The table pairs are sorted by key.
628 -- @param t     The table to iterate
629 -- @return      Function value containing the corresponding iterator
630 function kspairs(t)
631         return _sortiter( t )
632 end
633
634 --- Return a key, value iterator for the given table.
635 -- The table pairs are sorted by value.
636 -- @param t     The table to iterate
637 -- @return      Function value containing the corresponding iterator
638 function vspairs(t)
639         return _sortiter( t, function (a,b) return t[a] < t[b] end )
640 end
641
642
643 --
644 -- System utility functions
645 --
646
647 --- Test whether the current system is operating in big endian mode.
648 -- @return      Boolean value indicating whether system is big endian
649 function bigendian()
650         return string.byte(string.dump(function() end), 7) == 0
651 end
652
653 --- Execute given commandline and gather stdout.
654 -- @param command       String containing command to execute
655 -- @return                      String containing the command's stdout
656 function exec(command)
657         local pp   = io.popen(command)
658         local data = pp:read("*a")
659         pp:close()
660
661         return data
662 end
663
664 --- Return a line-buffered iterator over the output of given command.
665 -- @param command       String containing the command to execute
666 -- @return                      Iterator
667 function execi(command)
668         local pp = io.popen(command)
669
670         return pp and function()
671                 local line = pp:read()
672                 
673                 if not line then
674                         pp:close()
675                 end
676                 
677                 return line
678         end
679 end
680
681 -- Deprecated
682 function execl(command)
683         local pp   = io.popen(command)
684         local line = ""
685         local data = {}
686
687         while true do
688                 line = pp:read()
689                 if (line == nil) then break end
690                 table.insert(data, line)
691         end
692         pp:close()
693
694         return data
695 end
696
697 --- Returns the absolute path to LuCI base directory.
698 -- @return              String containing the directory path
699 function libpath()
700         return require "luci.fs".dirname(require "luci.debug".__file__)
701 end
702
703
704 --
705 -- Coroutine safe xpcall and pcall versions modified for Luci
706 -- original version:
707 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
708 --
709 -- Copyright © 2005 Kepler Project.
710 -- Permission is hereby granted, free of charge, to any person obtaining a
711 -- copy of this software and associated documentation files (the "Software"),
712 -- to deal in the Software without restriction, including without limitation
713 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
714 -- and/or sell copies of the Software, and to permit persons to whom the
715 -- Software is furnished to do so, subject to the following conditions:
716 --
717 -- The above copyright notice and this permission notice shall be
718 -- included in all copies or substantial portions of the Software.
719 --
720 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
721 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
722 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
723 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
724 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
725 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
726 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
727
728 local performResume, handleReturnValue
729 local oldpcall, oldxpcall = pcall, xpcall
730 coxpt = {}
731 setmetatable(coxpt, {__mode = "kv"})
732
733 -- Identity function for copcall
734 local function copcall_id(trace, ...)
735   return ...
736 end
737
738 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
739 -- @param f             Lua function to be called protected
740 -- @param err   Custom error handler
741 -- @param ...   Parameters passed to the function
742 -- @return              A boolean whether the function call succeeded and the return
743 --                              values of either the function or the error handler
744 function coxpcall(f, err, ...)
745         local res, co = oldpcall(coroutine.create, f)
746         if not res then
747                 local params = {...}
748                 local newf = function() return f(unpack(params)) end
749                 co = coroutine.create(newf)
750         end
751         local c = coroutine.running()
752         coxpt[co] = coxpt[c] or c or 0
753
754         return performResume(err, co, ...)
755 end
756
757 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
758 -- @param f             Lua function to be called protected
759 -- @param ...   Parameters passed to the function
760 -- @return              A boolean whether the function call succeeded and the returns
761 --                              values of the function or the error object
762 function copcall(f, ...)
763         return coxpcall(f, copcall_id, ...)
764 end
765
766 -- Handle return value of protected call
767 function handleReturnValue(err, co, status, ...)
768         if not status then
769                 return false, err(debug.traceback(co, (...)), ...)
770         end
771         if coroutine.status(co) == 'suspended' then
772                 return performResume(err, co, coroutine.yield(...))
773         else
774                 return true, ...
775         end
776 end
777
778 -- Resume execution of protected function call
779 function performResume(err, co, ...)
780         return handleReturnValue(err, co, coroutine.resume(co, ...))
781 end