Moved luci.sys.exec, luci.sys.execl and luci.sys.bigendian to luci.util
[project/luci.git] / libs / core / luasrc / util.lua
index 17ee1cd64d16f7c50d4316e1405b939d92ec0a6b..2f6cfad4c21a8f1e06e01a0343be4b9111946029 100644 (file)
@@ -24,15 +24,15 @@ limitations under the License.
 
 ]]--
 
--- LuCI utility functions.
+--- LuCI utility functions.
 module("luci.util", package.seeall)
 
 --
 -- Class helper routines
 --
 
---- Creates a Class object (Python-style object model)
--- Creates a new class object which can be instantiated by calling itself.
+--- Create a Class object (Python-style object model).
+-- The class object can be instantiated by calling itself.
 -- Any class functions or shared parameters can be attached to this object.
 -- Attaching a table to the class object makes this table shared between
 -- all instances of this class. For object parameters use the __init__ function.
@@ -75,7 +75,7 @@ end
 --- Test whether the given object is an instance of the given class.
 -- @param object       Object instance
 -- @param class                Class object to test against
--- @return                     Boolean indicating wheather the object is an instance
+-- @return                     Boolean indicating whether the object is an instance
 -- @see                                class
 -- @see                                clone
 function instanceof(object, class)
@@ -162,7 +162,7 @@ end
 
 --- Write given object to stderr.
 -- @param obj  Value to write to stderr
--- @return             Boolean indicating wheather the write operation was successful
+-- @return             Boolean indicating whether the write operation was successful
 function perror(obj)
        return io.stderr:write(tostring(obj) .. "\n")
 end
@@ -186,10 +186,10 @@ end
 -- String and data manipulation routines
 --
 
---- Escapes all occurences of the given character in given string.
+--- Escapes all occurrences of the given character in given string.
 -- @param s    String value containing unescaped characters
 -- @param c    String value with character to escape (optional, defaults to "\")
--- @return     String value with each occurence of character escaped with "\"
+-- @return     String value with each occurrence of character escaped with "\"
 function escape(s, c)
        c = c or "\\"
        return s:gsub(c, "\\" .. c)
@@ -206,15 +206,15 @@ function pcdata(value)
        return value:gsub(">", ">")
 end
 
---- Splits given string on a defined seperator sequence and return a table
+--- Splits given string on a defined separator sequence and return a table
 -- containing the resulting substrings. The optional max parameter specifies
 -- the number of bytes to process, regardless of the actual length of the given
--- string. The optional last parameter, regex, sepcifies wheather the separator
+-- string. The optional last parameter, regex, specifies whether the separator
 -- sequence is interpreted as regular expression.
 -- @param str          String value containing the data to split up
 -- @param pat          String with separator pattern (optional, defaults to "\n")
--- @param max          Num of bytes to process (optional, default is string length)
--- @param regexp       Boolean indicating wheather to interprete the separator
+-- @param max          Maximum times to split (optional)
+-- @param regex        Boolean indicating whether to interpret the separator
 --                                     pattern as regular expression (optional, default is false)
 -- @return                     Table containing the resulting substrings
 function split(str, pat, max, regex)
@@ -259,7 +259,7 @@ function trim(str)
 end
 
 --- Parse certain units from the given string and return the canonical integer
--- value or 0 if the unit is unknown. Upper- or lowercase is irrelevant.
+-- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
 -- Recognized units are:
 --     o "y"   - one year   (60*60*24*366)
 --  o "m"      - one month  (60*60*24*31)
@@ -320,7 +320,7 @@ end
 --- Combines two or more numerically indexed tables into one.
 -- @param tbl1 Table value to combine
 -- @param tbl2 Table value to combine
--- @param tblN More values to combine
+-- @param ...  More tables to combine
 -- @return             Table value containing all values of given tables
 function combine(...)
        local result = {}
@@ -335,7 +335,7 @@ end
 --- Checks whether the given table contains the given value.
 -- @param table        Table value
 -- @param value        Value to search within the given table
--- @return             Boolean indicating wheather the given value occurs within table
+-- @return             Boolean indicating whether the given value occurs within table
 function contains(table, value)
        for k, v in pairs(table) do
                if value == v then
@@ -358,7 +358,7 @@ end
 
 --- Clones the given object and return it's copy.
 -- @param object       Table value to clone
--- @param deep         Boolean indicating wheather to do recursive cloning
+-- @param deep         Boolean indicating whether to do recursive cloning
 -- @return                     Cloned table value
 function clone(object, deep)
        local copy = {}
@@ -376,17 +376,82 @@ function clone(object, deep)
 end
 
 
+--- Create a dynamic table which automatically creates subtables.
+-- @return     Dynamic Table
+function dtable()
+        return setmetatable({}, { __index =
+                function(tbl, key)
+                        return rawget(tbl, key)
+                         or rawget(rawset(tbl, key, dtable()), key)
+                end
+        })
+end
+
+
+-- Serialize the contents of a table value.
+function _serialize_table(t)
+       local data = ""
+       for k, v in pairs(t) do
+               k = serialize_data(k)
+               v = serialize_data(v)
+               data = data .. ( #data > 0 and ", " or "" ) ..
+                       '[' .. k .. '] = ' .. v
+       end
+       return data
+end
+
+--- Recursively serialize given data to lua code, suitable for restoring
+-- with loadstring().
+-- @param val  Value containing the data to serialize
+-- @return             String value containing the serialized code
+-- @see                        restore_data
+-- @see                        get_bytecode
+function serialize_data(val)
+       if val == nil then
+               return "nil"
+       elseif type(val) == "number" then
+               return val
+       elseif type(val) == "string" then
+               return string.format("%q", val)
+       elseif type(val) == "boolean" then
+               return val and "true" or "false"
+       elseif type(val) == "function" then
+               return string.format("loadstring(%q)", get_bytecode(val))
+       elseif type(val) == "table" then
+               return "{ " .. _serialize_table(val) .. " }"
+       else
+               return '"[unhandled data type:' .. type(val) .. ']"'
+       end
+end
+
+--- Restore data previously serialized with serialize_data().
+-- @param str  String containing the data to restore
+-- @return             Value containing the restored data structure
+-- @see                        serialize_data
+-- @see                        get_bytecode
+function restore_data(str)
+       return loadstring("return " .. str)()
+end
+
+
 --
 -- Byte code manipulation routines
 --
 
---- Return the current runtime bytecode of the given function. The byte code
+--- Return the current runtime bytecode of the given data. The byte code
 -- will be stripped before it is returned.
--- @param f    Function value to return as bytecode
--- @return     String value containing the bytecode of the given function
-function get_bytecode(f)
-       local d = string.dump(f)
-       return d and strip_bytecode(d)
+-- @param val  Value to return as bytecode
+-- @return             String value containing the bytecode of the given data
+function get_bytecode(val)
+       local code
+
+       if type(val) == "function" then
+               code = string.dump(val)
+       else
+               code = string.dump( loadstring( "return " .. serialize_data(val) ) )
+       end
+
+       return code and strip_bytecode(code)
 end
 
 --- Strips unnescessary lua bytecode from given string. Information like line
@@ -508,6 +573,45 @@ function vspairs(t)
 end
 
 
+--
+-- System utility functions
+--
+
+--- Test whether the current system is operating in big endian mode.
+-- @return     Boolean value indicating whether system is big endian
+function bigendian()
+       return string.byte(string.dump(function() end), 7) == 0
+end
+
+--- Execute given commandline and gather stdout.
+-- @param command      String containing command to execute
+-- @return                     String containing the command's stdout
+function exec(command)
+       local pp   = io.popen(command)
+       local data = pp:read("*a")
+       pp:close()
+
+       return data
+end
+
+--- Execute given commandline and gather stdout.
+-- @param command      String containing the command to execute
+-- @return                     Table containing the command's stdout splitted up in lines
+function execl(command)
+       local pp   = io.popen(command)
+       local line = ""
+       local data = {}
+
+       while true do
+               line = pp:read()
+               if (line == nil) then break end
+               table.insert(data, line)
+       end
+       pp:close()
+
+       return data
+end
+
 --
 -- Coroutine safe xpcall and pcall versions modified for Luci
 -- original version: