5 Several common useful Lua functions
11 Copyright 2008 Steven Barth <steven@midlink.org>
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
17 http://www.apache.org/licenses/LICENSE-2.0
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.
27 local io = require "io"
28 local math = require "math"
29 local table = require "table"
30 local debug = require "debug"
31 local string = require "string"
32 local coroutine = require "coroutine"
34 local getmetatable, setmetatable = getmetatable, setmetatable
35 local getfenv, setfenv = getfenv, setfenv
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
41 --- LuCI utility functions.
45 -- Pythonic string formatting extension
47 getmetatable("").__mod = function(a, b)
50 elseif type(b) == "table" then
51 return a:format(unpack(b))
59 -- Class helper routines
62 --- Create a Class object (Python-style object model).
63 -- The class object can be instantiated by calling itself.
64 -- Any class functions or shared parameters can be attached to this object.
65 -- Attaching a table to the class object makes this table shared between
66 -- all instances of this class. For object parameters use the __init__ function.
67 -- Classes can inherit member functions and values from a base class.
68 -- Class can be instantiated by calling them. All parameters will be passed
69 -- to the __init__ function of this class - if such a function exists.
70 -- The __init__ function must be used to set any object parameters that are not shared
71 -- with other objects of this class. Any return values will be ignored.
72 -- @param base The base class to inherit from (optional)
73 -- @return A class object
79 local create = function(class, ...)
80 local inst = setmetatable({}, {__index = class})
89 local classmeta = {__call = create}
92 classmeta.__index = base
95 setmetatable(class, classmeta)
99 --- Test whether the given object is an instance of the given class.
100 -- @param object Object instance
101 -- @param class Class object to test against
102 -- @return Boolean indicating whether the object is an instance
105 function instanceof(object, class)
106 local meta = getmetatable(object)
107 while meta and meta.__index do
108 if meta.__index == class then
111 meta = getmetatable(meta.__index)
118 -- Scope manipulation routines
121 --- Replace a function scope with a shallow copy of itself.
122 -- This is useful if you want to get rid of several unwanted side effects
123 -- while changing the scope of a certain Lua function.
124 -- @param f Lua function
126 setfenv(f, clone(getfenv(f)))
129 --- Store given object associated with given key in the scope of a function.
130 -- @param f Lua function
131 -- @param key String value containg the key of the object to store
132 -- @param obj Object to store in the scope
133 -- @return Always nil
136 function extfenv(f, key, obj)
137 local scope = getfenv(f)
141 --- Extend the scope of a function with the contents of a table
142 -- @param f Lua function
143 -- @param key String value containg the key of the object to store
144 -- @param obj Object to store in the scope
145 -- @return Always nil
148 function updfenv(f, extscope)
149 update(getfenv(f), extscope)
152 --- Create a new or get an already existing thread local store associated with
153 -- the current active coroutine. A thread local store is private a table object
154 -- whose values can't be accessed from outside of the running coroutine.
155 -- @return Table value representing the corresponding thread local store
156 function threadlocal()
159 local function get(self, key)
160 local c = coroutine.running()
161 local thread = coxpt[c] or c or 0
162 if not rawget(self, thread) then
165 return rawget(self, thread)[key]
168 local function set(self, key, value)
169 local c = coroutine.running()
170 local thread = coxpt[c] or c or 0
171 if not rawget(self, thread) then
172 rawset(self, thread, {})
174 rawget(self, thread)[key] = value
177 setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"})
184 -- Debugging routines
187 --- Write given object to stderr.
188 -- @param obj Value to write to stderr
189 -- @return Boolean indicating whether the write operation was successful
191 return io.stderr:write(tostring(obj) .. "\n")
194 --- Recursively dumps a table to stdout, useful for testing and debugging.
195 -- @param t Table value to dump
196 -- @param maxdepth Maximum depth
197 -- @return Always nil
198 function dumptable(t, maxdepth, i, seen)
200 seen = seen or setmetatable({}, {__mode="k"})
202 for k,v in pairs(t) do
203 perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
204 if type(v) == "table" and (not maxdepth or i < maxdepth) then
207 dumptable(v, maxdepth, i+1, seen)
209 perror(string.rep("\t", i) .. "*** RECURSION ***")
217 -- String and data manipulation routines
220 --- Escapes all occurrences of the given character in given string.
221 -- @param s String value containing unescaped characters
222 -- @param c String value with character to escape (optional, defaults to "\")
223 -- @return String value with each occurrence of character escaped with "\"
224 function escape(s, c)
226 return s:gsub(c, "\\" .. c)
229 --- Create valid XML PCDATA from given string.
230 -- @param value String value containing the data to escape
231 -- @return String value containing the escaped data
232 function pcdata(value)
233 if not value then return end
234 value = tostring(value)
235 value = value:gsub("&", "&")
236 value = value:gsub('"', """)
237 value = value:gsub("'", "'")
238 value = value:gsub("<", "<")
239 return value:gsub(">", ">")
242 --- Strip HTML tags from given string.
243 -- @param value String containing the HTML text
244 -- @return String with HTML tags stripped of
245 function striptags(s)
246 return pcdata(s:gsub("</?[A-Za-z][A-Za-z0-9:_%-]*[^>]*>", " "):gsub("%s+", " "))
249 --- Splits given string on a defined separator sequence and return a table
250 -- containing the resulting substrings. The optional max parameter specifies
251 -- the number of bytes to process, regardless of the actual length of the given
252 -- string. The optional last parameter, regex, specifies whether the separator
253 -- sequence is interpreted as regular expression.
254 -- @param str String value containing the data to split up
255 -- @param pat String with separator pattern (optional, defaults to "\n")
256 -- @param max Maximum times to split (optional)
257 -- @param regex Boolean indicating whether to interpret the separator
258 -- pattern as regular expression (optional, default is false)
259 -- @return Table containing the resulting substrings
260 function split(str, pat, max, regex)
280 local s, e = str:find(pat, c, not regex)
282 if s and max < 0 then
283 table.insert(t, str:sub(c))
285 table.insert(t, str:sub(c, s and s - 1))
287 c = e and e + 1 or #str + 1
288 until not s or max < 0
293 --- Remove leading and trailing whitespace from given string value.
294 -- @param str String value containing whitespace padded data
295 -- @return String value with leading and trailing space removed
297 return (str:gsub("^%s*(.-)%s*$", "%1"))
300 --- Parse certain units from the given string and return the canonical integer
301 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
302 -- Recognized units are:
303 -- o "y" - one year (60*60*24*366)
304 -- o "m" - one month (60*60*24*31)
305 -- o "w" - one week (60*60*24*7)
306 -- o "d" - one day (60*60*24)
307 -- o "h" - one hour (60*60)
308 -- o "min" - one minute (60)
309 -- o "kb" - one kilobyte (1024)
310 -- o "mb" - one megabyte (1024*1024)
311 -- o "gb" - one gigabyte (1024*1024*1024)
312 -- o "kib" - one si kilobyte (1000)
313 -- o "mib" - one si megabyte (1000*1000)
314 -- o "gib" - one si gigabyte (1000*1000*1000)
315 -- @param ustr String containing a numerical value with trailing unit
316 -- @return Number containing the canonical value
317 function parse_units(ustr)
324 y = 60 * 60 * 24 * 366,
325 m = 60 * 60 * 24 * 31,
326 w = 60 * 60 * 24 * 7,
334 gb = 1024 * 1024 * 1024,
336 -- storage sizes (si)
339 gib = 1000 * 1000 * 1000
342 -- parse input string
343 for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
345 local num = spec:gsub("[^0-9%.]+$","")
346 local spn = spec:gsub("^[0-9%.]+", "")
348 if map[spn] or map[spn:sub(1,1)] then
349 val = val + num * ( map[spn] or map[spn:sub(1,1)] )
359 --- Combines two or more numerically indexed tables into one.
360 -- @param tbl1 Table value to combine
361 -- @param tbl2 Table value to combine
362 -- @param ... More tables to combine
363 -- @return Table value containing all values of given tables
364 function combine(...)
366 for i, a in ipairs(arg) do
367 for j, v in ipairs(a) do
368 table.insert(result, v)
374 --- Checks whether the given table contains the given value.
375 -- @param table Table value
376 -- @param value Value to search within the given table
377 -- @return Boolean indicating whether the given value occurs within table
378 function contains(table, value)
379 for k, v in pairs(table) do
387 --- Update values in given table with the values from the second given table.
388 -- Both table are - in fact - merged together.
389 -- @param t Table which should be updated
390 -- @param updates Table containing the values to update
391 -- @return Always nil
392 function update(t, updates)
393 for k, v in pairs(updates) do
398 --- Retrieve all keys of given associative table.
399 -- @param t Table to extract keys from
400 -- @return Sorted table containing the keys
404 for k, _ in kspairs(t) do
405 table.insert( keys, k )
411 --- Clones the given object and return it's copy.
412 -- @param object Table value to clone
413 -- @param deep Boolean indicating whether to do recursive cloning
414 -- @return Cloned table value
415 function clone(object, deep)
418 for k, v in pairs(object) do
419 if deep and type(v) == "table" then
425 return setmetatable(copy, getmetatable(object))
429 --- Create a dynamic table which automatically creates subtables.
430 -- @return Dynamic Table
432 return setmetatable({}, { __index =
434 return rawget(tbl, key)
435 or rawget(rawset(tbl, key, dtable()), key)
441 -- Serialize the contents of a table value.
442 function _serialize_table(t, seen)
443 assert(not seen[t], "Recursion detected.")
450 for k, v in pairs(t) do
451 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
452 k = serialize_data(k, seen)
453 v = serialize_data(v, seen)
454 data = data .. ( #data > 0 and ", " or "" ) ..
455 '[' .. k .. '] = ' .. v
462 local v = serialize_data(t[i], seen)
463 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
466 return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
469 --- Recursively serialize given data to lua code, suitable for restoring
470 -- with loadstring().
471 -- @param val Value containing the data to serialize
472 -- @return String value containing the serialized code
475 function serialize_data(val, seen)
476 seen = seen or setmetatable({}, {__mode="k"})
480 elseif type(val) == "number" then
482 elseif type(val) == "string" then
484 elseif type(val) == "boolean" then
485 return val and "true" or "false"
486 elseif type(val) == "function" then
487 return "loadstring(%q)" % get_bytecode(val)
488 elseif type(val) == "table" then
489 return "{ " .. _serialize_table(val, seen) .. " }"
491 return '"[unhandled data type:' .. type(val) .. ']"'
495 --- Restore data previously serialized with serialize_data().
496 -- @param str String containing the data to restore
497 -- @return Value containing the restored data structure
498 -- @see serialize_data
500 function restore_data(str)
501 return loadstring("return " .. str)()
506 -- Byte code manipulation routines
509 --- Return the current runtime bytecode of the given data. The byte code
510 -- will be stripped before it is returned.
511 -- @param val Value to return as bytecode
512 -- @return String value containing the bytecode of the given data
513 function get_bytecode(val)
516 if type(val) == "function" then
517 code = string.dump(val)
519 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
522 return code and strip_bytecode(code)
525 --- Strips unnescessary lua bytecode from given string. Information like line
526 -- numbers and debugging numbers will be discarded. Original version by
527 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
528 -- @param code String value containing the original lua byte code
529 -- @return String value containing the stripped lua byte code
530 function strip_bytecode(code)
531 local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
534 subint = function(code, i, l)
537 val = val * 256 + code:byte(i + n - 1)
542 subint = function(code, i, l)
545 val = val * 256 + code:byte(i + n - 1)
552 strip_function = function(code)
553 local count, offset = subint(code, 1, size)
554 local stripped, dirty = string.rep("\0", size), offset + count
555 offset = offset + count + int * 2 + 4
556 offset = offset + int + subint(code, offset, int) * ins
557 count, offset = subint(code, offset, int)
560 t, offset = subint(code, offset, 1)
564 offset = offset + size + subint(code, offset, size)
566 offset = offset + num
567 elseif t == 254 or t == 9 then
568 offset = offset + lnum
571 count, offset = subint(code, offset, int)
572 stripped = stripped .. code:sub(dirty, offset - 1)
574 local proto, off = strip_function(code:sub(offset, -1))
575 stripped, offset = stripped .. proto, offset + off - 1
577 offset = offset + subint(code, offset, int) * int + int
578 count, offset = subint(code, offset, int)
580 offset = offset + subint(code, offset, size) + size + int * 2
582 count, offset = subint(code, offset, int)
584 offset = offset + subint(code, offset, size) + size
586 stripped = stripped .. string.rep("\0", int * 3)
587 return stripped, offset
590 return code:sub(1,12) .. strip_function(code:sub(13,-1))
595 -- Sorting iterator functions
598 function _sortiter( t, f )
601 for k, v in pairs(t) do
602 table.insert( keys, k )
606 local _len = table.getn( keys )
608 table.sort( keys, f )
613 return keys[_pos], t[keys[_pos]]
618 --- Return a key, value iterator which returns the values sorted according to
619 -- the provided callback function.
620 -- @param t The table to iterate
621 -- @param f A callback function to decide the order of elements
622 -- @return Function value containing the corresponding iterator
624 return _sortiter( t, f )
627 --- Return a key, value iterator for the given table.
628 -- The table pairs are sorted by key.
629 -- @param t The table to iterate
630 -- @return Function value containing the corresponding iterator
632 return _sortiter( t )
635 --- Return a key, value iterator for the given table.
636 -- The table pairs are sorted by value.
637 -- @param t The table to iterate
638 -- @return Function value containing the corresponding iterator
640 return _sortiter( t, function (a,b) return t[a] < t[b] end )
645 -- System utility functions
648 --- Test whether the current system is operating in big endian mode.
649 -- @return Boolean value indicating whether system is big endian
651 return string.byte(string.dump(function() end), 7) == 0
654 --- Execute given commandline and gather stdout.
655 -- @param command String containing command to execute
656 -- @return String containing the command's stdout
657 function exec(command)
658 local pp = io.popen(command)
659 local data = pp:read("*a")
665 --- Return a line-buffered iterator over the output of given command.
666 -- @param command String containing the command to execute
668 function execi(command)
669 local pp = io.popen(command)
671 return pp and function()
672 local line = pp:read()
683 function execl(command)
684 local pp = io.popen(command)
690 if (line == nil) then break end
691 table.insert(data, line)
698 --- Returns the absolute path to LuCI base directory.
699 -- @return String containing the directory path
701 return require "luci.fs".dirname(require "luci.debug".__file__)
706 -- Coroutine safe xpcall and pcall versions modified for Luci
708 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
710 -- Copyright © 2005 Kepler Project.
711 -- Permission is hereby granted, free of charge, to any person obtaining a
712 -- copy of this software and associated documentation files (the "Software"),
713 -- to deal in the Software without restriction, including without limitation
714 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
715 -- and/or sell copies of the Software, and to permit persons to whom the
716 -- Software is furnished to do so, subject to the following conditions:
718 -- The above copyright notice and this permission notice shall be
719 -- included in all copies or substantial portions of the Software.
721 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
722 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
723 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
724 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
725 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
726 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
727 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
729 local performResume, handleReturnValue
730 local oldpcall, oldxpcall = pcall, xpcall
732 setmetatable(coxpt, {__mode = "kv"})
734 -- Identity function for copcall
735 local function copcall_id(trace, ...)
739 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
740 -- @param f Lua function to be called protected
741 -- @param err Custom error handler
742 -- @param ... Parameters passed to the function
743 -- @return A boolean whether the function call succeeded and the return
744 -- values of either the function or the error handler
745 function coxpcall(f, err, ...)
746 local res, co = oldpcall(coroutine.create, f)
749 local newf = function() return f(unpack(params)) end
750 co = coroutine.create(newf)
752 local c = coroutine.running()
753 coxpt[co] = coxpt[c] or c or 0
755 return performResume(err, co, ...)
758 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
759 -- @param f Lua function to be called protected
760 -- @param ... Parameters passed to the function
761 -- @return A boolean whether the function call succeeded and the returns
762 -- values of the function or the error object
763 function copcall(f, ...)
764 return coxpcall(f, copcall_id, ...)
767 -- Handle return value of protected call
768 function handleReturnValue(err, co, status, ...)
770 return false, err(debug.traceback(co, (...)), ...)
772 if coroutine.status(co) == 'suspended' then
773 return performResume(err, co, coroutine.yield(...))
779 -- Resume execution of protected function call
780 function performResume(err, co, ...)
781 return handleReturnValue(err, co, coroutine.resume(co, ...))