* luci/core: util.lua: implement min(utes) in parse_units()
[project/luci.git] / libs / core / luasrc / util.lua
index 0559fff..074b435 100644 (file)
@@ -96,6 +96,13 @@ function contains(table, value)
 end
 
 
+-- Dumps and strips a Lua-Function
+function dump(f)
+       local d = string.dump(f)
+       return d and strip_bytecode(d)
+end
+
+
 -- Dumps a table to stdout (useful for testing and debugging)
 function dumptable(t, i)
        i = i or 0
@@ -181,12 +188,80 @@ function split(str, pat, max, regex)
        return t
 end
 
+
+-- Strips lua bytecode
+-- Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
+function strip_bytecode(dump)
+       local version, format, endian, int, size, ins, num, lnum = dump:byte(5, 12)
+       local subint
+       if endian == 1 then
+               subint = function(dump, i, l)
+                       local val = 0
+                       for n = l, 1, -1 do
+                               val = val * 256 + dump:byte(i + n - 1)
+                       end
+                       return val, i + l
+               end
+       else
+               subint = function(dump, i, l)
+                       local val = 0
+                       for n = 1, l, 1 do
+                               val = val * 256 + dump:byte(i + n - 1)
+                       end
+                       return val, i + l
+               end
+       end
+    
+       local strip_function
+       strip_function = function(dump)
+               local count, offset = subint(dump, 1, size)
+               local stripped, dirty = string.rep("\0", size), offset + count
+               offset = offset + count + int * 2 + 4
+               offset = offset + int + subint(dump, offset, int) * ins
+               count, offset = subint(dump, offset, int)
+               for n = 1, count do
+                       local t
+                       t, offset = subint(dump, offset, 1)
+                       if t == 1 then
+                               offset = offset + 1
+                       elseif t == 4 then
+                               offset = offset + size + subint(dump, offset, size)
+                       elseif t == 3 then
+                               offset = offset + num
+                       elseif t == 254 then
+                               offset = offset + lnum
+                       end
+               end
+               count, offset = subint(dump, offset, int)
+               stripped = stripped .. dump:sub(dirty, offset - 1)
+               for n = 1, count do
+                       local proto, off = strip_function(dump:sub(offset, -1))
+                       stripped, offset = stripped .. proto, offset + off - 1
+               end
+               offset = offset + subint(dump, offset, int) * int + int
+               count, offset = subint(dump, offset, int)
+               for n = 1, count do
+                       offset = offset + subint(dump, offset, size) + size + int * 2
+               end
+               count, offset = subint(dump, offset, int)
+               for n = 1, count do
+                       offset = offset + subint(dump, offset, size) + size
+               end
+               stripped = stripped .. string.rep("\0", int * 3)
+               return stripped, offset
+       end
+       
+       return dump:sub(1,12) .. strip_function(dump:sub(13,-1))
+end
+
+
 -- Removes whitespace from beginning and end of a string
 function trim(str)
        local s = str:gsub("^%s*(.-)%s*$", "%1")
        return s
 end
 
+
 -- Updates given table with new values
 function update(t, updates)
        for k, v in pairs(updates) do
@@ -212,4 +287,48 @@ function validate(value, cast_number, cast_int)
        end
        
        return value
-end
\ No newline at end of file
+end
+
+
+-- Parse units from a string and return integer value
+function parse_units(ustr)
+
+        local val = 0
+
+        -- unit map
+        local map = {
+                -- date stuff
+                y   = 60 * 60 * 24 * 366,
+                m   = 60 * 60 * 24 * 31,
+                w   = 60 * 60 * 24 * 7,
+                d   = 60 * 60 * 24,
+                h   = 60 * 60,
+               min = 60,
+
+                -- storage sizes
+                kb  = 1024,
+                mb  = 1024 * 1024,
+                gb  = 1024 * 1024 * 1024,
+
+                -- storage sizes (si)
+                kib = 1000,
+                mib = 1000 * 1000,
+                gib = 1000 * 1000 * 1000
+        }
+
+        -- parse input string
+        for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
+
+                local num = spec:gsub("[^0-9%.]+$","")
+                local spn = spec:gsub("^[0-9%.]+", "")
+
+                if map[spn] or map[spn:sub(1,1)] then
+                        val = val + num * ( map[spn] or map[spn:sub(1,1)] )
+                else
+                        val = val + num
+                end
+        end
+
+
+       return val
+end