X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fcore%2Fluasrc%2Futil.lua;h=bde803f710612ad09512b7da36d41327111bd71b;hp=53e46a99dc85176b1461720d0446954ad1512e85;hb=8772db16759352146a069f2bb7394a4a4213ba0f;hpb=a3cf596d37e4116a7068daaa724270a0898cb7da diff --git a/libs/core/luasrc/util.lua b/libs/core/luasrc/util.lua index 53e46a99d..bde803f71 100644 --- a/libs/core/luasrc/util.lua +++ b/libs/core/luasrc/util.lua @@ -31,13 +31,14 @@ local debug = require "debug" local ldebug = require "luci.debug" local string = require "string" local coroutine = require "coroutine" -local cutil = require "luci.cutil" +local tparser = require "luci.template.parser" local getmetatable, setmetatable = getmetatable, setmetatable local rawget, rawset, unpack = rawget, rawset, unpack local tostring, type, assert = tostring, type, assert -local ipairs, pairs, loadstring = ipairs, pairs, loadstring +local ipairs, pairs, next, loadstring = ipairs, pairs, next, loadstring local require, pcall, xpcall = require, pcall, xpcall +local collectgarbage, get_memory_limit = collectgarbage, get_memory_limit --- LuCI utility functions. module "luci.util" @@ -45,17 +46,17 @@ module "luci.util" -- -- Pythonic string formatting extension -- ---[[ getmetatable("").__mod = function(a, b) if not b then return a elseif type(b) == "table" then + for k, _ in pairs(b) do if type(b[k]) == "userdata" then b[k] = tostring(b[k]) end end return a:format(unpack(b)) else + if type(b) == "userdata" then b = tostring(b) end return a:format(b) end end -]]-- -- @@ -63,7 +64,6 @@ end -- -- Instantiates a class ---[[ local function _instantiate(class, ...) local inst = setmetatable({}, {__index = class}) @@ -73,7 +73,6 @@ local function _instantiate(class, ...) return inst end -]]-- --- Create a Class object (Python-style object model). -- The class object can be instantiated by calling itself. @@ -89,15 +88,12 @@ end -- @return A class object -- @see instanceof -- @see clone ---[[ function class(base) return setmetatable({}, { __call = _instantiate, __index = base }) end -]]-- -class = cutil.class --- Test whether the given object is an instance of the given class. -- @param object Object instance @@ -105,7 +101,6 @@ class = cutil.class -- @return Boolean indicating whether the object is an instance -- @see class -- @see clone ---[[ function instanceof(object, class) local meta = getmetatable(object) while meta and meta.__index do @@ -116,42 +111,37 @@ function instanceof(object, class) end return false end -]]-- -instanceof = cutil.instanceof -- -- Scope manipulation routines -- ---- Create a new or get an already existing thread local store associated with --- the current active coroutine. A thread local store is private a table object --- whose values can't be accessed from outside of the running coroutine. --- @return Table value representing the corresponding thread local store -function threadlocal() - local tbl = {} - - local function get(self, key) - local c = coroutine.running() - local thread = coxpt[c] or c or 0 - if not rawget(self, thread) then - return nil - end - return rawget(self, thread)[key] - end +local tl_meta = { + __mode = "k", + + __index = function(self, key) + local t = rawget(self, coxpt[coroutine.running()] + or coroutine.running() or 0) + return t and t[key] + end, - local function set(self, key, value) - local c = coroutine.running() - local thread = coxpt[c] or c or 0 - if not rawget(self, thread) then - rawset(self, thread, {}) + __newindex = function(self, key, value) + local c = coxpt[coroutine.running()] or coroutine.running() or 0 + if not rawget(self, c) then + rawset(self, c, { [key] = value }) + else + rawget(self, c)[key] = value end - rawget(self, thread)[key] = value end +} - setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"}) - - return tbl +--- Create a new or get an already existing thread local store associated with +-- the current active coroutine. A thread local store is private a table object +-- whose values can't be accessed from outside of the running coroutine. +-- @return Table value representing the corresponding thread local store +function threadlocal(tbl) + return setmetatable(tbl or {}, tl_meta) end @@ -204,24 +194,15 @@ end --- Create valid XML PCDATA from given string. -- @param value String value containing the data to escape -- @return String value containing the escaped data ---[[ function pcdata(value) - return value and tostring(value):gsub("[&\"'<>]", { - ["&"] = "&", - ['"'] = """, - ["'"] = "'", - ["<"] = "<", - [">"] = ">" - }) + return value and tparser.sanitize_pcdata(tostring(value)) end -]]-- -pcdata = cutil.pcdata --- Strip HTML tags from given string. -- @param value String containing the HTML text -- @return String with HTML tags stripped of function striptags(s) - return pcdata(s:gsub("]*>", " "):gsub("%s+", " ")) + return pcdata(tostring(s):gsub("]*>", " "):gsub("%s+", " ")) end --- Splits given string on a defined separator sequence and return a table @@ -271,12 +252,9 @@ end --- Remove leading and trailing whitespace from given string value. -- @param str String value containing whitespace padded data -- @return String value with leading and trailing space removed ---[[ function trim(str) return (str:gsub("^%s*(.-)%s*$", "%1")) end -]]-- -trim = cutil.trim --- Count the occurences of given substring in given string. -- @param str String to search in @@ -288,6 +266,36 @@ function cmatch(str, pat) return count end +--- Return a matching iterator for the given value. The iterator will return +-- one token per invocation, the tokens are separated by whitespace. If the +-- input value is a table, it is transformed into a string first. A nil value +-- will result in a valid interator which aborts with the first invocation. +-- @param val The value to scan (table, string or nil) +-- @return Iterator which returns one token per call +function imatch(v) + if type(v) == "table" then + local k = nil + return function() + k = next(v, k) + return v[k] + end + + elseif type(v) == "number" or type(v) == "boolean" then + local x = true + return function() + if x then + x = false + return tostring(v) + end + end + + elseif type(v) == "userdata" or type(v) == "string" then + return tostring(v):gmatch("%S+") + end + + return function() end +end + --- Parse certain units from the given string and return the canonical integer -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant. -- Recognized units are: @@ -531,7 +539,7 @@ function get_bytecode(val) code = string.dump( loadstring( "return " .. serialize_data(val) ) ) end - return code and strip_bytecode(code) + return code -- and strip_bytecode(code) end --- Strips unnescessary lua bytecode from given string. Information like line @@ -560,10 +568,10 @@ function strip_bytecode(code) end end - local strip_function - strip_function = function(code) + local function strip_function(code) local count, offset = subint(code, 1, size) - local stripped, dirty = string.rep("\0", size), offset + count + local stripped = { string.rep("\0", size) } + local dirty = offset + count offset = offset + count + int * 2 + 4 offset = offset + int + subint(code, offset, int) * ins count, offset = subint(code, offset, int) @@ -581,10 +589,11 @@ function strip_bytecode(code) end end count, offset = subint(code, offset, int) - stripped = stripped .. code:sub(dirty, offset - 1) + stripped[#stripped+1] = code:sub(dirty, offset - 1) for n = 1, count do local proto, off = strip_function(code:sub(offset, -1)) - stripped, offset = stripped .. proto, offset + off - 1 + stripped[#stripped+1] = proto + offset = offset + off - 1 end offset = offset + subint(code, offset, int) * int + int count, offset = subint(code, offset, int) @@ -595,8 +604,8 @@ function strip_bytecode(code) for n = 1, count do offset = offset + subint(code, offset, size) + size end - stripped = stripped .. string.rep("\0", int * 3) - return stripped, offset + stripped[#stripped+1] = string.rep("\0", int * 3) + return table.concat(stripped), offset end return code:sub(1,12) .. strip_function(code:sub(13,-1)) @@ -709,7 +718,7 @@ end --- Returns the absolute path to LuCI base directory. -- @return String containing the directory path function libpath() - return require "luci.fs".dirname(ldebug.__file__) + return require "nixio.fs".dirname(ldebug.__file__) end @@ -780,11 +789,12 @@ function handleReturnValue(err, co, status, ...) if not status then return false, err(debug.traceback(co, (...)), ...) end - if coroutine.status(co) == 'suspended' then - return performResume(err, co, coroutine.yield(...)) - else + + if coroutine.status(co) ~= 'suspended' then return true, ... end + + return performResume(err, co, coroutine.yield(...)) end -- Resume execution of protected function call