Module:Util

Documentation Module:Util/doc

This is a meta module.
This module is meant to be used only by other modules. It should not be invoked in wikitext.

Overview

Provides utility functions for programming modules.

Structure

Group Function Description
string trim Trim whitespaces and tabs from a string.
trimend Trim whitespaces and tabs from the end of a string.
split Splits a string into a table.
table deepcopy Copy table and all subtables. (Deep-copy)
merge Recursively merges and/or deep-copies tables.

Usage

This module should be loaded with require().


local util = {
    string = {},
    table = {},
}

-- ----------------------------------------------------------------------------
-- util.string
-- ----------------------------------------------------------------------------

--- Trim whitespaces and tabs from a string.
-- @param #string 'str': String to trim.
-- @return #string: Trimmed string.
function util.string.trim(str)
    local l = 1
    while string.sub(str, l, l) == ' ' or string.sub(str, l, l) == '\t' do
        l = l + 1
    end
    local r = string.len(str)
    while string.sub(str, r, r) == ' ' or string.sub(str, r, r) == '\t' do
        r = r - 1
    end
    return string.sub(str, l, r)
end

--- Trim whitespaces and tabs from the end of a string.
-- @param #string 'str': String to trim.
-- @return #string: Trimmed string.
function util.string.trimend(str)
    local r = string.len(str)
    while string.sub(str, r, r) == ' ' or string.sub(str, r, r) == '\t' do
        r = r - 1
    end
    return string.sub(str, 1, r)
end

--- Splits a string into a table.
--- This does essentially the same thing as mw.text.split, but with significantly better performance.
-- @param #string 'str': String to split.
-- @param #string 'pattern': Pattern to use for splitting. Default is '%s'.
-- @param #bool 'plain': If true, pattern is interpreted as a literal string. Optional.
-- @return #table: Table of strings.
function util.string.split(str, pattern, plain)
    if str then
        pattern = pattern or "%s"
        local out = {}
        local init = 1
        local split_start, split_end = string.find(str, pattern, init, plain)
        while split_start do
            out[#out+1] = string.sub(str, init, split_start-1)
            init = split_end+1
            split_start, split_end = string.find(str, pattern, init, plain)
        end
        out[#out+1] = string.sub(str, init)
        return out
    end
    return nil
end

-- ----------------------------------------------------------------------------
-- util.table
-- ----------------------------------------------------------------------------

--- Copy table and all subtables. (Deep-copy)
-- @param 'object': Object to copy.
-- @return New table if 'object' is a table, otherwise returns 'object'.
function util.table.deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for i, v in pairs(object) do
            new_table[_copy(i)] = _copy(v)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

--- Recursively merges and/or deep-copies tables.
-- Entries in later tables override entries in earlier ones, unless both entries are themselves tables, in which case they are recursively merged.
-- Non-merged tables are deep-copied, so that the result is brand new.
-- @param #table 'tables': Tables to merge.
-- @return #table: Merged tables.
function util.table.merge(tables)
    local ret = {}
    for _, tbl in ipairs(tables) do
        for k, v in pairs(tbl) do
            if (type(v) == "table") then
                if (type(ret[k] or false) == "table") then
                    ret[k] = util.table.merge{ret[k], v}
                else
                    ret[k] = util.table.deepcopy(v)
                end
            else
                ret[k] = v
            end
        end
    end
    return ret
end

return util