More C-Functions (luci.cutil.instanceof, luci.cutil.pcdata)
[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 function trim(str)
275         return (str:gsub("^%s*(.-)%s*$", "%1"))
276 end
277
278 --- Count the occurences of given substring in given string.
279 -- @param str           String to search in
280 -- @param pattern       String containing pattern to find
281 -- @return                      Number of found occurences
282 function cmatch(str, pat)
283         local count = 0
284         for _ in str:gmatch(pat) do count = count + 1 end
285         return count
286 end
287
288 --- Parse certain units from the given string and return the canonical integer
289 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
290 -- Recognized units are:
291 --      o "y"   - one year   (60*60*24*366)
292 --  o "m"       - one month  (60*60*24*31)
293 --  o "w"       - one week   (60*60*24*7)
294 --  o "d"       - one day    (60*60*24)
295 --  o "h"       - one hour       (60*60)
296 --  o "min"     - one minute (60)
297 --  o "kb"  - one kilobyte (1024)
298 --  o "mb"      - one megabyte (1024*1024)
299 --  o "gb"      - one gigabyte (1024*1024*1024)
300 --  o "kib" - one si kilobyte (1000)
301 --  o "mib"     - one si megabyte (1000*1000)
302 --  o "gib"     - one si gigabyte (1000*1000*1000)
303 -- @param ustr  String containing a numerical value with trailing unit
304 -- @return              Number containing the canonical value
305 function parse_units(ustr)
306
307         local val = 0
308
309         -- unit map
310         local map = {
311                 -- date stuff
312                 y   = 60 * 60 * 24 * 366,
313                 m   = 60 * 60 * 24 * 31,
314                 w   = 60 * 60 * 24 * 7,
315                 d   = 60 * 60 * 24,
316                 h   = 60 * 60,
317                 min = 60,
318
319                 -- storage sizes
320                 kb  = 1024,
321                 mb  = 1024 * 1024,
322                 gb  = 1024 * 1024 * 1024,
323
324                 -- storage sizes (si)
325                 kib = 1000,
326                 mib = 1000 * 1000,
327                 gib = 1000 * 1000 * 1000
328         }
329
330         -- parse input string
331         for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
332
333                 local num = spec:gsub("[^0-9%.]+$","")
334                 local spn = spec:gsub("^[0-9%.]+", "")
335
336                 if map[spn] or map[spn:sub(1,1)] then
337                         val = val + num * ( map[spn] or map[spn:sub(1,1)] )
338                 else
339                         val = val + num
340                 end
341         end
342
343
344         return val
345 end
346
347 -- also register functions above in the central string class for convenience
348 string.escape      = escape
349 string.pcdata      = pcdata
350 string.striptags   = striptags
351 string.split       = split
352 string.trim        = trim
353 string.cmatch      = cmatch
354 string.parse_units = parse_units
355
356
357 --- Appends numerically indexed tables or single objects to a given table.
358 -- @param src   Target table
359 -- @param ...   Objects to insert
360 -- @return              Target table
361 function append(src, ...)
362         for i, a in ipairs({...}) do
363                 if type(a) == "table" then
364                         for j, v in ipairs(a) do
365                                 src[#src+1] = v
366                         end
367                 else
368                         src[#src+1] = a
369                 end
370         end
371         return src
372 end
373
374 --- Combines two or more numerically indexed tables and single objects into one table.
375 -- @param tbl1  Table value to combine
376 -- @param tbl2  Table value to combine
377 -- @param ...   More tables to combine
378 -- @return              Table value containing all values of given tables
379 function combine(...)
380         return append({}, ...)
381 end
382
383 --- Checks whether the given table contains the given value.
384 -- @param table Table value
385 -- @param value Value to search within the given table
386 -- @return              Boolean indicating whether the given value occurs within table
387 function contains(table, value)
388         for k, v in pairs(table) do
389                 if value == v then
390                         return k
391                 end
392         end
393         return false
394 end
395
396 --- Update values in given table with the values from the second given table.
397 -- Both table are - in fact - merged together.
398 -- @param t                     Table which should be updated
399 -- @param updates       Table containing the values to update
400 -- @return                      Always nil
401 function update(t, updates)
402         for k, v in pairs(updates) do
403                 t[k] = v
404         end
405 end
406
407 --- Retrieve all keys of given associative table.
408 -- @param t     Table to extract keys from
409 -- @return      Sorted table containing the keys
410 function keys(t)
411         local keys = { }
412         if t then
413                 for k, _ in kspairs(t) do
414                         keys[#keys+1] = k
415                 end
416         end
417         return keys
418 end
419
420 --- Clones the given object and return it's copy.
421 -- @param object        Table value to clone
422 -- @param deep          Boolean indicating whether to do recursive cloning
423 -- @return                      Cloned table value
424 function clone(object, deep)
425         local copy = {}
426
427         for k, v in pairs(object) do
428                 if deep and type(v) == "table" then
429                         v = clone(v, deep)
430                 end
431                 copy[k] = v
432         end
433
434         return setmetatable(copy, getmetatable(object))
435 end
436
437
438 --- Create a dynamic table which automatically creates subtables.
439 -- @return      Dynamic Table
440 function dtable()
441         return setmetatable({}, { __index =
442                 function(tbl, key)
443                         return rawget(tbl, key)
444                          or rawget(rawset(tbl, key, dtable()), key)
445                 end
446         })
447 end
448
449
450 -- Serialize the contents of a table value.
451 function _serialize_table(t, seen)
452         assert(not seen[t], "Recursion detected.")
453         seen[t] = true
454
455         local data  = ""
456         local idata = ""
457         local ilen  = 0
458
459         for k, v in pairs(t) do
460                 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
461                         k = serialize_data(k, seen)
462                         v = serialize_data(v, seen)
463                         data = data .. ( #data > 0 and ", " or "" ) ..
464                                 '[' .. k .. '] = ' .. v
465                 elseif k > ilen then
466                         ilen = k
467                 end
468         end
469
470         for i = 1, ilen do
471                 local v = serialize_data(t[i], seen)
472                 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
473         end
474
475         return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
476 end
477
478 --- Recursively serialize given data to lua code, suitable for restoring
479 -- with loadstring().
480 -- @param val   Value containing the data to serialize
481 -- @return              String value containing the serialized code
482 -- @see                 restore_data
483 -- @see                 get_bytecode
484 function serialize_data(val, seen)
485         seen = seen or setmetatable({}, {__mode="k"})
486
487         if val == nil then
488                 return "nil"
489         elseif type(val) == "number" then
490                 return val
491         elseif type(val) == "string" then
492                 return "%q" % val
493         elseif type(val) == "boolean" then
494                 return val and "true" or "false"
495         elseif type(val) == "function" then
496                 return "loadstring(%q)" % get_bytecode(val)
497         elseif type(val) == "table" then
498                 return "{ " .. _serialize_table(val, seen) .. " }"
499         else
500                 return '"[unhandled data type:' .. type(val) .. ']"'
501         end
502 end
503
504 --- Restore data previously serialized with serialize_data().
505 -- @param str   String containing the data to restore
506 -- @return              Value containing the restored data structure
507 -- @see                 serialize_data
508 -- @see                 get_bytecode
509 function restore_data(str)
510         return loadstring("return " .. str)()
511 end
512
513
514 --
515 -- Byte code manipulation routines
516 --
517
518 --- Return the current runtime bytecode of the given data. The byte code
519 -- will be stripped before it is returned.
520 -- @param val   Value to return as bytecode
521 -- @return              String value containing the bytecode of the given data
522 function get_bytecode(val)
523         local code
524
525         if type(val) == "function" then
526                 code = string.dump(val)
527         else
528                 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
529         end
530
531         return code and strip_bytecode(code)
532 end
533
534 --- Strips unnescessary lua bytecode from given string. Information like line
535 -- numbers and debugging numbers will be discarded. Original version by
536 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
537 -- @param code  String value containing the original lua byte code
538 -- @return              String value containing the stripped lua byte code
539 function strip_bytecode(code)
540         local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
541         local subint
542         if endian == 1 then
543                 subint = function(code, i, l)
544                         local val = 0
545                         for n = l, 1, -1 do
546                                 val = val * 256 + code:byte(i + n - 1)
547                         end
548                         return val, i + l
549                 end
550         else
551                 subint = function(code, i, l)
552                         local val = 0
553                         for n = 1, l, 1 do
554                                 val = val * 256 + code:byte(i + n - 1)
555                         end
556                         return val, i + l
557                 end
558         end
559
560         local strip_function
561         strip_function = function(code)
562                 local count, offset = subint(code, 1, size)
563                 local stripped, dirty = string.rep("\0", size), offset + count
564                 offset = offset + count + int * 2 + 4
565                 offset = offset + int + subint(code, offset, int) * ins
566                 count, offset = subint(code, offset, int)
567                 for n = 1, count do
568                         local t
569                         t, offset = subint(code, offset, 1)
570                         if t == 1 then
571                                 offset = offset + 1
572                         elseif t == 4 then
573                                 offset = offset + size + subint(code, offset, size)
574                         elseif t == 3 then
575                                 offset = offset + num
576                         elseif t == 254 or t == 9 then
577                                 offset = offset + lnum
578                         end
579                 end
580                 count, offset = subint(code, offset, int)
581                 stripped = stripped .. code:sub(dirty, offset - 1)
582                 for n = 1, count do
583                         local proto, off = strip_function(code:sub(offset, -1))
584                         stripped, offset = stripped .. proto, offset + off - 1
585                 end
586                 offset = offset + subint(code, offset, int) * int + int
587                 count, offset = subint(code, offset, int)
588                 for n = 1, count do
589                         offset = offset + subint(code, offset, size) + size + int * 2
590                 end
591                 count, offset = subint(code, offset, int)
592                 for n = 1, count do
593                         offset = offset + subint(code, offset, size) + size
594                 end
595                 stripped = stripped .. string.rep("\0", int * 3)
596                 return stripped, offset
597         end
598
599         return code:sub(1,12) .. strip_function(code:sub(13,-1))
600 end
601
602
603 --
604 -- Sorting iterator functions
605 --
606
607 function _sortiter( t, f )
608         local keys = { }
609
610         for k, v in pairs(t) do
611                 keys[#keys+1] = k
612         end
613
614         local _pos = 0
615
616         table.sort( keys, f )
617
618         return function()
619                 _pos = _pos + 1
620                 if _pos <= #keys then
621                         return keys[_pos], t[keys[_pos]]
622                 end
623         end
624 end
625
626 --- Return a key, value iterator which returns the values sorted according to
627 -- the provided callback function.
628 -- @param t     The table to iterate
629 -- @param f A callback function to decide the order of elements
630 -- @return      Function value containing the corresponding iterator
631 function spairs(t,f)
632         return _sortiter( t, f )
633 end
634
635 --- Return a key, value iterator for the given table.
636 -- The table pairs are sorted by key.
637 -- @param t     The table to iterate
638 -- @return      Function value containing the corresponding iterator
639 function kspairs(t)
640         return _sortiter( t )
641 end
642
643 --- Return a key, value iterator for the given table.
644 -- The table pairs are sorted by value.
645 -- @param t     The table to iterate
646 -- @return      Function value containing the corresponding iterator
647 function vspairs(t)
648         return _sortiter( t, function (a,b) return t[a] < t[b] end )
649 end
650
651
652 --
653 -- System utility functions
654 --
655
656 --- Test whether the current system is operating in big endian mode.
657 -- @return      Boolean value indicating whether system is big endian
658 function bigendian()
659         return string.byte(string.dump(function() end), 7) == 0
660 end
661
662 --- Execute given commandline and gather stdout.
663 -- @param command       String containing command to execute
664 -- @return                      String containing the command's stdout
665 function exec(command)
666         local pp   = io.popen(command)
667         local data = pp:read("*a")
668         pp:close()
669
670         return data
671 end
672
673 --- Return a line-buffered iterator over the output of given command.
674 -- @param command       String containing the command to execute
675 -- @return                      Iterator
676 function execi(command)
677         local pp = io.popen(command)
678
679         return pp and function()
680                 local line = pp:read()
681
682                 if not line then
683                         pp:close()
684                 end
685
686                 return line
687         end
688 end
689
690 -- Deprecated
691 function execl(command)
692         local pp   = io.popen(command)
693         local line = ""
694         local data = {}
695
696         while true do
697                 line = pp:read()
698                 if (line == nil) then break end
699                 data[#data+1] = line
700         end
701         pp:close()
702
703         return data
704 end
705
706 --- Returns the absolute path to LuCI base directory.
707 -- @return              String containing the directory path
708 function libpath()
709         return require "luci.fs".dirname(ldebug.__file__)
710 end
711
712
713 --
714 -- Coroutine safe xpcall and pcall versions modified for Luci
715 -- original version:
716 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
717 --
718 -- Copyright © 2005 Kepler Project.
719 -- Permission is hereby granted, free of charge, to any person obtaining a
720 -- copy of this software and associated documentation files (the "Software"),
721 -- to deal in the Software without restriction, including without limitation
722 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
723 -- and/or sell copies of the Software, and to permit persons to whom the
724 -- Software is furnished to do so, subject to the following conditions:
725 --
726 -- The above copyright notice and this permission notice shall be
727 -- included in all copies or substantial portions of the Software.
728 --
729 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
730 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
731 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
732 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
733 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
734 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
735 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
736
737 local performResume, handleReturnValue
738 local oldpcall, oldxpcall = pcall, xpcall
739 coxpt = {}
740 setmetatable(coxpt, {__mode = "kv"})
741
742 -- Identity function for copcall
743 local function copcall_id(trace, ...)
744   return ...
745 end
746
747 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
748 -- @param f             Lua function to be called protected
749 -- @param err   Custom error handler
750 -- @param ...   Parameters passed to the function
751 -- @return              A boolean whether the function call succeeded and the return
752 --                              values of either the function or the error handler
753 function coxpcall(f, err, ...)
754         local res, co = oldpcall(coroutine.create, f)
755         if not res then
756                 local params = {...}
757                 local newf = function() return f(unpack(params)) end
758                 co = coroutine.create(newf)
759         end
760         local c = coroutine.running()
761         coxpt[co] = coxpt[c] or c or 0
762
763         return performResume(err, co, ...)
764 end
765
766 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
767 -- @param f             Lua function to be called protected
768 -- @param ...   Parameters passed to the function
769 -- @return              A boolean whether the function call succeeded and the returns
770 --                              values of the function or the error object
771 function copcall(f, ...)
772         return coxpcall(f, copcall_id, ...)
773 end
774
775 -- Handle return value of protected call
776 function handleReturnValue(err, co, status, ...)
777         if not status then
778                 return false, err(debug.traceback(co, (...)), ...)
779         end
780         if coroutine.status(co) == 'suspended' then
781                 return performResume(err, co, coroutine.yield(...))
782         else
783                 return true, ...
784         end
785 end
786
787 -- Resume execution of protected function call
788 function performResume(err, co, ...)
789         return handleReturnValue(err, co, coroutine.resume(co, ...))
790 end