+--- 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
+
+--- Count the occurences of given substring in given string.
+-- @param str String to search in
+-- @param pattern String containing pattern to find
+-- @return Number of found occurences
+function cmatch(str, pat)
+ local count = 0
+ for _ in str:gmatch(pat) do count = count + 1 end
+ 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 v == nil then
+ v = ""
+ elseif type(v) == "table" then
+ v = table.concat(v, " ")
+ elseif type(v) ~= "string" then
+ v = tostring(v)
+ end
+
+ return v:gmatch("%S+")
+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:
+-- o "y" - one year (60*60*24*366)
+-- o "m" - one month (60*60*24*31)
+-- o "w" - one week (60*60*24*7)
+-- o "d" - one day (60*60*24)
+-- o "h" - one hour (60*60)
+-- o "min" - one minute (60)
+-- o "kb" - one kilobyte (1024)
+-- o "mb" - one megabyte (1024*1024)
+-- o "gb" - one gigabyte (1024*1024*1024)
+-- o "kib" - one si kilobyte (1000)
+-- o "mib" - one si megabyte (1000*1000)
+-- o "gib" - one si gigabyte (1000*1000*1000)
+-- @param ustr String containing a numerical value with trailing unit
+-- @return Number containing the canonical 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
+
+-- also register functions above in the central string class for convenience
+string.escape = escape
+string.pcdata = pcdata
+string.striptags = striptags
+string.split = split
+string.trim = trim
+string.cmatch = cmatch
+string.parse_units = parse_units
+
+
+--- Appends numerically indexed tables or single objects to a given table.
+-- @param src Target table
+-- @param ... Objects to insert
+-- @return Target table
+function append(src, ...)
+ for i, a in ipairs({...}) do
+ if type(a) == "table" then
+ for j, v in ipairs(a) do
+ src[#src+1] = v
+ end
+ else
+ src[#src+1] = a
+ end
+ end
+ return src
+end
+
+--- Combines two or more numerically indexed tables and single objects into one table.
+-- @param tbl1 Table value to combine
+-- @param tbl2 Table value to combine
+-- @param ... More tables to combine
+-- @return Table value containing all values of given tables
+function combine(...)
+ return append({}, ...)
+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 whether the given value occurs within table
+function contains(table, value)
+ for k, v in pairs(table) do
+ if value == v then
+ return k
+ end
+ end
+ return false
+end
+
+--- Update values in given table with the values from the second given table.
+-- Both table are - in fact - merged together.
+-- @param t Table which should be updated
+-- @param updates Table containing the values to update
+-- @return Always nil
+function update(t, updates)
+ for k, v in pairs(updates) do
+ t[k] = v
+ end
+end
+
+--- Retrieve all keys of given associative table.
+-- @param t Table to extract keys from
+-- @return Sorted table containing the keys
+function keys(t)
+ local keys = { }
+ if t then
+ for k, _ in kspairs(t) do
+ keys[#keys+1] = k
+ end
+ end
+ return keys
+end