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