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