5 Several common useful Lua functions
8 Copyright 2008 Steven Barth <steven@midlink.org>
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
24 local io = require "io"
25 local math = require "math"
26 local table = require "table"
27 local debug = require "debug"
28 local ldebug = require "luci.debug"
29 local string = require "string"
30 local coroutine = require "coroutine"
31 local tparser = require "luci.template.parser"
33 local _ubus = require "ubus"
34 local _ubus_connection = nil
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, next, loadstring = ipairs, pairs, next, loadstring
40 local require, pcall, xpcall = require, pcall, xpcall
41 local collectgarbage, get_memory_limit = collectgarbage, get_memory_limit
43 --- LuCI utility functions.
47 -- Pythonic string formatting extension
49 getmetatable("").__mod = function(a, b)
52 elseif type(b) == "table" then
53 for k, _ in pairs(b) do if type(b[k]) == "userdata" then b[k] = tostring(b[k]) end end
54 return a:format(unpack(b))
56 if type(b) == "userdata" then b = tostring(b) end
63 -- Class helper routines
66 -- Instantiates a class
67 local function _instantiate(class, ...)
68 local inst = setmetatable({}, {__index = class})
77 --- Create a Class object (Python-style object model).
78 -- The class object can be instantiated by calling itself.
79 -- Any class functions or shared parameters can be attached to this object.
80 -- Attaching a table to the class object makes this table shared between
81 -- all instances of this class. For object parameters use the __init__ function.
82 -- Classes can inherit member functions and values from a base class.
83 -- Class can be instantiated by calling them. All parameters will be passed
84 -- to the __init__ function of this class - if such a function exists.
85 -- The __init__ function must be used to set any object parameters that are not shared
86 -- with other objects of this class. Any return values will be ignored.
87 -- @param base The base class to inherit from (optional)
88 -- @return A class object
92 return setmetatable({}, {
93 __call = _instantiate,
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
104 function instanceof(object, class)
105 local meta = getmetatable(object)
106 while meta and meta.__index do
107 if meta.__index == class then
110 meta = getmetatable(meta.__index)
117 -- Scope manipulation routines
123 __index = function(self, key)
124 local t = rawget(self, coxpt[coroutine.running()]
125 or coroutine.running() or 0)
129 __newindex = function(self, key, value)
130 local c = coxpt[coroutine.running()] or coroutine.running() or 0
131 local r = rawget(self, c)
133 rawset(self, c, { [key] = value })
140 --- Create a new or get an already existing thread local store associated with
141 -- the current active coroutine. A thread local store is private a table object
142 -- whose values can't be accessed from outside of the running coroutine.
143 -- @return Table value representing the corresponding thread local store
144 function threadlocal(tbl)
145 return setmetatable(tbl or {}, tl_meta)
150 -- Debugging routines
153 --- Write given object to stderr.
154 -- @param obj Value to write to stderr
155 -- @return Boolean indicating whether the write operation was successful
157 return io.stderr:write(tostring(obj) .. "\n")
160 --- Recursively dumps a table to stdout, useful for testing and debugging.
161 -- @param t Table value to dump
162 -- @param maxdepth Maximum depth
163 -- @return Always nil
164 function dumptable(t, maxdepth, i, seen)
166 seen = seen or setmetatable({}, {__mode="k"})
168 for k,v in pairs(t) do
169 perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
170 if type(v) == "table" and (not maxdepth or i < maxdepth) then
173 dumptable(v, maxdepth, i+1, seen)
175 perror(string.rep("\t", i) .. "*** RECURSION ***")
183 -- String and data manipulation routines
186 --- Create valid XML PCDATA from given string.
187 -- @param value String value containing the data to escape
188 -- @return String value containing the escaped data
189 function pcdata(value)
190 return value and tparser.pcdata(tostring(value))
193 --- Strip HTML tags from given string.
194 -- @param value String containing the HTML text
195 -- @return String with HTML tags stripped of
196 function striptags(value)
197 return value and tparser.striptags(tostring(value))
200 --- Splits given string on a defined separator sequence and return a table
201 -- containing the resulting substrings. The optional max parameter specifies
202 -- the number of bytes to process, regardless of the actual length of the given
203 -- string. The optional last parameter, regex, specifies whether the separator
204 -- sequence is interpreted as regular expression.
205 -- @param str String value containing the data to split up
206 -- @param pat String with separator pattern (optional, defaults to "\n")
207 -- @param max Maximum times to split (optional)
208 -- @param regex Boolean indicating whether to interpret the separator
209 -- pattern as regular expression (optional, default is false)
210 -- @return Table containing the resulting substrings
211 function split(str, pat, max, regex)
231 local s, e = str:find(pat, c, not regex)
233 if s and max < 0 then
236 t[#t+1] = str:sub(c, s and s - 1)
238 c = e and e + 1 or #str + 1
239 until not s or max < 0
244 --- Remove leading and trailing whitespace from given string value.
245 -- @param str String value containing whitespace padded data
246 -- @return String value with leading and trailing space removed
248 return (str:gsub("^%s*(.-)%s*$", "%1"))
251 --- Count the occurences of given substring in given string.
252 -- @param str String to search in
253 -- @param pattern String containing pattern to find
254 -- @return Number of found occurences
255 function cmatch(str, pat)
257 for _ in str:gmatch(pat) do count = count + 1 end
261 --- Return a matching iterator for the given value. The iterator will return
262 -- one token per invocation, the tokens are separated by whitespace. If the
263 -- input value is a table, it is transformed into a string first. A nil value
264 -- will result in a valid interator which aborts with the first invocation.
265 -- @param val The value to scan (table, string or nil)
266 -- @return Iterator which returns one token per call
268 if type(v) == "table" then
275 elseif type(v) == "number" or type(v) == "boolean" then
284 elseif type(v) == "userdata" or type(v) == "string" then
285 return tostring(v):gmatch("%S+")
288 return function() end
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)
315 y = 60 * 60 * 24 * 366,
316 m = 60 * 60 * 24 * 31,
317 w = 60 * 60 * 24 * 7,
325 gb = 1024 * 1024 * 1024,
327 -- storage sizes (si)
330 gib = 1000 * 1000 * 1000
333 -- parse input string
334 for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
336 local num = spec:gsub("[^0-9%.]+$","")
337 local spn = spec:gsub("^[0-9%.]+", "")
339 if map[spn] or map[spn:sub(1,1)] then
340 val = val + num * ( map[spn] or map[spn:sub(1,1)] )
350 -- also register functions above in the central string class for convenience
351 string.pcdata = pcdata
352 string.striptags = striptags
355 string.cmatch = cmatch
356 string.parse_units = parse_units
359 --- Appends numerically indexed tables or single objects to a given table.
360 -- @param src Target table
361 -- @param ... Objects to insert
362 -- @return Target table
363 function append(src, ...)
364 for i, a in ipairs({...}) do
365 if type(a) == "table" then
366 for j, v in ipairs(a) do
376 --- Combines two or more numerically indexed tables and single objects into one table.
377 -- @param tbl1 Table value to combine
378 -- @param tbl2 Table value to combine
379 -- @param ... More tables to combine
380 -- @return Table value containing all values of given tables
381 function combine(...)
382 return append({}, ...)
385 --- Checks whether the given table contains the given value.
386 -- @param table Table value
387 -- @param value Value to search within the given table
388 -- @return Boolean indicating whether the given value occurs within table
389 function contains(table, value)
390 for k, v in pairs(table) do
398 --- Update values in given table with the values from the second given table.
399 -- Both table are - in fact - merged together.
400 -- @param t Table which should be updated
401 -- @param updates Table containing the values to update
402 -- @return Always nil
403 function update(t, updates)
404 for k, v in pairs(updates) do
409 --- Retrieve all keys of given associative table.
410 -- @param t Table to extract keys from
411 -- @return Sorted table containing the keys
415 for k, _ in kspairs(t) do
422 --- Clones the given object and return it's copy.
423 -- @param object Table value to clone
424 -- @param deep Boolean indicating whether to do recursive cloning
425 -- @return Cloned table value
426 function clone(object, deep)
429 for k, v in pairs(object) do
430 if deep and type(v) == "table" then
436 return setmetatable(copy, getmetatable(object))
440 --- Create a dynamic table which automatically creates subtables.
441 -- @return Dynamic Table
443 return setmetatable({}, { __index =
445 return rawget(tbl, key)
446 or rawget(rawset(tbl, key, dtable()), key)
452 -- Serialize the contents of a table value.
453 function _serialize_table(t, seen)
454 assert(not seen[t], "Recursion detected.")
461 for k, v in pairs(t) do
462 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
463 k = serialize_data(k, seen)
464 v = serialize_data(v, seen)
465 data = data .. ( #data > 0 and ", " or "" ) ..
466 '[' .. k .. '] = ' .. v
473 local v = serialize_data(t[i], seen)
474 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
477 return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
480 --- Recursively serialize given data to lua code, suitable for restoring
481 -- with loadstring().
482 -- @param val Value containing the data to serialize
483 -- @return String value containing the serialized code
486 function serialize_data(val, seen)
487 seen = seen or setmetatable({}, {__mode="k"})
491 elseif type(val) == "number" then
493 elseif type(val) == "string" then
495 elseif type(val) == "boolean" then
496 return val and "true" or "false"
497 elseif type(val) == "function" then
498 return "loadstring(%q)" % get_bytecode(val)
499 elseif type(val) == "table" then
500 return "{ " .. _serialize_table(val, seen) .. " }"
502 return '"[unhandled data type:' .. type(val) .. ']"'
506 --- Restore data previously serialized with serialize_data().
507 -- @param str String containing the data to restore
508 -- @return Value containing the restored data structure
509 -- @see serialize_data
511 function restore_data(str)
512 return loadstring("return " .. str)()
517 -- Byte code manipulation routines
520 --- Return the current runtime bytecode of the given data. The byte code
521 -- will be stripped before it is returned.
522 -- @param val Value to return as bytecode
523 -- @return String value containing the bytecode of the given data
524 function get_bytecode(val)
527 if type(val) == "function" then
528 code = string.dump(val)
530 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
533 return code -- and strip_bytecode(code)
536 --- Strips unnescessary lua bytecode from given string. Information like line
537 -- numbers and debugging numbers will be discarded. Original version by
538 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
539 -- @param code String value containing the original lua byte code
540 -- @return String value containing the stripped lua byte code
541 function strip_bytecode(code)
542 local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
545 subint = function(code, i, l)
548 val = val * 256 + code:byte(i + n - 1)
553 subint = function(code, i, l)
556 val = val * 256 + code:byte(i + n - 1)
562 local function strip_function(code)
563 local count, offset = subint(code, 1, size)
564 local stripped = { string.rep("\0", size) }
565 local dirty = offset + count
566 offset = offset + count + int * 2 + 4
567 offset = offset + int + subint(code, offset, int) * ins
568 count, offset = subint(code, offset, int)
571 t, offset = subint(code, offset, 1)
575 offset = offset + size + subint(code, offset, size)
577 offset = offset + num
578 elseif t == 254 or t == 9 then
579 offset = offset + lnum
582 count, offset = subint(code, offset, int)
583 stripped[#stripped+1] = code:sub(dirty, offset - 1)
585 local proto, off = strip_function(code:sub(offset, -1))
586 stripped[#stripped+1] = proto
587 offset = offset + off - 1
589 offset = offset + subint(code, offset, int) * int + int
590 count, offset = subint(code, offset, int)
592 offset = offset + subint(code, offset, size) + size + int * 2
594 count, offset = subint(code, offset, int)
596 offset = offset + subint(code, offset, size) + size
598 stripped[#stripped+1] = string.rep("\0", int * 3)
599 return table.concat(stripped), offset
602 return code:sub(1,12) .. strip_function(code:sub(13,-1))
607 -- Sorting iterator functions
610 function _sortiter( t, f )
614 for k, v in pairs(t) do
620 table.sort( keys, f )
624 if _pos <= #keys then
625 return keys[_pos], t[keys[_pos]], _pos
630 --- Return a key, value iterator which returns the values sorted according to
631 -- the provided callback function.
632 -- @param t The table to iterate
633 -- @param f A callback function to decide the order of elements
634 -- @return Function value containing the corresponding iterator
636 return _sortiter( t, f )
639 --- Return a key, value iterator for the given table.
640 -- The table pairs are sorted by key.
641 -- @param t The table to iterate
642 -- @return Function value containing the corresponding iterator
644 return _sortiter( t )
647 --- Return a key, value iterator for the given table.
648 -- The table pairs are sorted by value.
649 -- @param t The table to iterate
650 -- @return Function value containing the corresponding iterator
652 return _sortiter( t, function (a,b) return t[a] < t[b] end )
657 -- System utility functions
660 --- Test whether the current system is operating in big endian mode.
661 -- @return Boolean value indicating whether system is big endian
663 return string.byte(string.dump(function() end), 7) == 0
666 --- Execute given commandline and gather stdout.
667 -- @param command String containing command to execute
668 -- @return String containing the command's stdout
669 function exec(command)
670 local pp = io.popen(command)
671 local data = pp:read("*a")
677 --- Return a line-buffered iterator over the output of given command.
678 -- @param command String containing the command to execute
680 function execi(command)
681 local pp = io.popen(command)
683 return pp and function()
684 local line = pp:read()
695 function execl(command)
696 local pp = io.popen(command)
702 if (line == nil) then break end
710 --- Issue an ubus call.
711 -- @param object String containing the ubus object to call
712 -- @param method String containing the ubus method to call
713 -- @param values Table containing the values to pass
714 -- @return Table containin the ubus result
715 function ubus(object, method, data)
716 if not _ubus_connection then
717 _ubus_connection = _ubus.connect()
718 assert(_ubus_connection, "Unable to establish ubus connection")
721 if object and method then
722 if type(data) ~= "table" then
725 return _ubus_connection:call(object, method, data)
727 return _ubus_connection:signatures(object)
729 return _ubus_connection:objects()
733 --- Returns the absolute path to LuCI base directory.
734 -- @return String containing the directory path
736 return require "nixio.fs".dirname(ldebug.__file__)
741 -- Coroutine safe xpcall and pcall versions modified for Luci
743 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
745 -- Copyright © 2005 Kepler Project.
746 -- Permission is hereby granted, free of charge, to any person obtaining a
747 -- copy of this software and associated documentation files (the "Software"),
748 -- to deal in the Software without restriction, including without limitation
749 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
750 -- and/or sell copies of the Software, and to permit persons to whom the
751 -- Software is furnished to do so, subject to the following conditions:
753 -- The above copyright notice and this permission notice shall be
754 -- included in all copies or substantial portions of the Software.
756 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
757 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
758 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
759 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
760 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
761 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
762 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
764 local performResume, handleReturnValue
765 local oldpcall, oldxpcall = pcall, xpcall
767 setmetatable(coxpt, {__mode = "kv"})
769 -- Identity function for copcall
770 local function copcall_id(trace, ...)
774 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
775 -- @param f Lua function to be called protected
776 -- @param err Custom error handler
777 -- @param ... Parameters passed to the function
778 -- @return A boolean whether the function call succeeded and the return
779 -- values of either the function or the error handler
780 function coxpcall(f, err, ...)
781 local res, co = oldpcall(coroutine.create, f)
784 local newf = function() return f(unpack(params)) end
785 co = coroutine.create(newf)
787 local c = coroutine.running()
788 coxpt[co] = coxpt[c] or c or 0
790 return performResume(err, co, ...)
793 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
794 -- @param f Lua function to be called protected
795 -- @param ... Parameters passed to the function
796 -- @return A boolean whether the function call succeeded and the returns
797 -- values of the function or the error object
798 function copcall(f, ...)
799 return coxpcall(f, copcall_id, ...)
802 -- Handle return value of protected call
803 function handleReturnValue(err, co, status, ...)
805 return false, err(debug.traceback(co, (...)), ...)
808 if coroutine.status(co) ~= 'suspended' then
812 return performResume(err, co, coroutine.yield(...))
815 -- Resume execution of protected function call
816 function performResume(err, co, ...)
817 return handleReturnValue(err, co, coroutine.resume(co, ...))